2.4.2 Примеры решений по обработке списков
Список, в котором нет ни одного элемента, называется пустым списком и обозначается "( )" или символом NIL. NIL - это и список и атом одновременно. NIL обозначает кроме этого, в логических выражениях логическую константу "ложь" (false). Логическое "да" (true) задается символом "Т".
S-выражения, которые не надо вычислять, помечают для интерпретатора апострофом " ' ". Вместо апострофа можно использовать функцию QUOTE. QUOTE - специальная функция с одним аргументом, которая возвращает в качестве значения этот аргумент.
> (quote (+ 1 2))
(+ 1 2)
или
> ('(+ 1 2))
(+ 1 2)
Функция EVAL обеспечивает дополнительный вызов интерпретатора Лиспа. При этом вызов может производится внутри вычисляемого S-выражения. Функция EVAL позволяет снять блокировку QUOTE. Quote и eval действуют во взаимно противоположенных направлениях и аннулируют эффект друг друга.
> (eval (quote (+ 1 2)))
3
Функция SETQ связывает символ со значением, но не вычисляет значение первого аргумента. Буква q на блокировку.
> (setq m 2)
2
> m
2
> (setq lis '(a b c))
(a b c)
Функция CAR возвращает в качестве значения первый элемент списка, т.е. голову.
> (car lis)
a
Функция CDR применяется к спискам, причем ее значением является хвост списка, получаемый из исходного списка после удаления из него головы.
> (cdr '(a b c))
(b c)
Функция CONS строит новый список из своих аргументов. Причем первый аргумент становится головой второго аргумента, который обязательно является списком.
> (cons 'a '(b c))
(a b c)
Функция APPEND объединяет два и более списков в один. Причем она образует новый список, убирая скобки вокруг аргументов и помещая их в один список.
> (append '(a b c) '(c d))
(a b c c d)
Функцию можно определить самим и использовать как встроенную. Чтобы определить функцию, необходимо: дать имя функции, определить параметры функции, определить, что должна делать функция. Для задания новых функций в Лиспе используется специальная форма DEFUN: (defun < имя-функции > < параметры > < тело-функции >)
> (defun double (num) (* 2 num))
double
> (double 10)
20
СOND является основным средством организации разветвления вычислений: (COND (<проверка-n> <действие-n>)). Обычно в качестве последнего условия пишется t, соответствующее ему выражение будет вычисляться в тех случаях, когда ни одно другое условие не выполняется.
Рассмотрим пример: если число положительное – 1, иначе 0
> (defun f(x)
(cond
((plusp x) 1)
(t 0)
) )
f
> (f 100)
1
> (f -100)
0
Предикат NULL проверяет, является ли аргумент пустым списком.
> (null '( ))
T
Числовой предикат PLUSP проверяет, является ли число положительным.
> (plusp 4)
T
> (plusp -18)
NIL
Числовой предикат MINUSP проверяет, является ли число отрицательным.
> (minus -6)
T
Рассмотрим несколько функций работы со списками.
; приведение всех элементов списка к одному уровню иерархии (defun open-skob (list1) (cond ((null list1) nil) ((numberp (car list1))(cons (car list1)(open-skob (cdr list1)))) ((listp (car list1)) (append (open-skob (car list1)) (open-skob (cdr list1)))) (t (open-skob (cdr list1))) ))
; поиск максимума (defun max0 (list1 max) (cond ((null list1) max) ((> (car list1) max) (max0 (cdr list1) (car list1))) (t (max0 (cdr list1) max)) ))
; удаление найденного максимума из списка (defun del (max list1) (cond ((null list1) nil) ((= max (car list1)) (del max (cdr list1))) (t (cons (car list1) (del max (cdr list1)))) )) (defun del0 (list1) (del (max0 list1 0) list1))
; нахождение 3 максимумов и вывод их в отдельный список (defun find-max (list1 k list2) (if (= k 3) list2 (find-max (del0 (open-skob list1)) (+ k 1) (cons (max0 (open-skob list1) 0) list2)))) |
Рисунок 2.1 – Листинг функции Find-max
Функция Find-max (рисунок 2.1) находит 3 максимальных числа в списке и выводит их в отдельный список.
> (setq list1 '((4 5) 6 (6 8 (3)) q1 (8 9 q 9)))
((4 5) 6 (6 8 (3)) Q1 (8 9 Q 9))
> (find-max list1 0 nil)
(6 8 9)
(defun sum-minus (x) (cond ((null x) 0) ((listp (car x))(+ (sum-minus (car x))(sum-minus (cdr x)))) ((minusp (car x)) (+ (car x)(sum-minus (cdr x)))) (t (sum-minus (cdr x))) )) |
Рисунок 2.2 – Листинг функции Sum-minus
Функция Sum-minus (рисунок 2.2) вычисляет сумму отрицательных чисел в списке.
> (sum-minus '(2 (-1 5 -2) 6))
-3
