На этом шаге мы рассмотрим примеры использования рекурсии по значению и по аргументам.
В этом разделе мы рассмотрим лишь несколько примеров.
(DEFUN REMOVE (LAMBDA (ATM LST) (COND ( (NULL LST) NIL) ( (EQ ATM (CAR LST)) ; Рекурсия по значению (REMOVE ATM (CDR LST)) ) ( T ; Рекурсия по аргументу (CONS (CAR LST) (REMOVE ATM (CDR LST))) ) ) ))
Список LST сокращается путем удаления всех идентичных ATM в смысле EQ элементов (вторая ветвь) и копирования в результирующий список (CONS) остальных элементов (третья ветвь) до тех пор, пока условие окончания (первая ветвь) не станет истинным. Результат формируется в процессе возврата.
Замечание. Функцию REMOVE можно определить с использованием предиката
EQUAL вместо EQ. С помощью такой функции можно удалять элементы, являющиеся списками!
(DEFUN MEMBERN (LAMBDA (X LST) (COND ( (NULL LST) NIL) ( T (OR (COND ( (ATOM (CAR LST)) (MEMBERN X (CDR LST)) ) ( T (OR (EQUAL X (CAR LST)) (MEMBERN X (CAR LST))) ) ) (MEMBERN X (CDR LST)) ) ) ) ))
(DEFUN SUMMA (LAMBDA (X LST) ; Подсчитать сумму мест, на которых в списке LST ; встречается элемент X (COND ( (NULL LST) 0 ) ( (EQ X (FOOT LST)) (+ (SUMMA X (HEAD LST)) (LENGTH LST)) ) ( T (SUMMA X (HEAD LST)) ) ) )) ; --------------------- (DEFUN FOOT (LAMBDA (LST) (CAR (REVERSE LST)) )) ; --------------------- (DEFUN HEAD (LAMBDA (LST) (REVERSE (CDR (REVERSE LST))) ))
(DEFUN REVERSE1 (LAMBDA (LST) ; "Обращение" списка LST на первом уровне ( (NULL LST) NIL) ( APPEND1 (REVERSE1 (CDR LST)) (CAR LST) ) )) ; -------------------------- (DEFUN APPEND1 (LAMBDA (LST X) ( (NULL LST) (CONS X NIL) ) ; Создание одноэлементного списка ( CONS (CAR LST) (APPEND1 (CDR LST) X) ) ))
На следующем шаге мы рассмотрим параллельную рекурсию.