Что-то заглохло доброе дело.
А между тем тут ещё есть чего сказать.
Чем больше будет знать lisp-программист о своих функциональных корнях -- тем ему зарплата больше. (Пусть это и авто-лисп программист, который и не лисп, на самом-то деле).
Ну вот, например.
Из математического определения рекурсии, плавно перенесенного на бинарное железо и Фон-Неймановскую архитектуру вытекает один не очень приятный факт: рекурсия всегда медленнее итерации. Обидно до слез (-:
Но, как известно, problems have solutions. Медлительность рекурсии обусловлена наглым захавыванием рекурсивной функцией памяти на передачу огромного числа аргументов самой себе.
Передавать, скажем, указатели ей религия не позволяет, мало-ли что там она сама над своими данными сделает? А вдруг попортит? Поэтому мы передаем данные целиком.
На счастье нашего бинарного железа, существует особая форма рекурсии -- tail recursion, или "хвостовая рекурсия".
Суть данной эзотерической техники сводится к простому действию, мы вводим "аккумулятор", который берет на себя ответственность хранить наши данные и уменьшать нагрузку на память.
Вот пример функции факториала, написанный с использованием хвостовой рекурсии:
(defun factorial (number)
(defun iterate (counter accumulator)
(if (= counter 0)
accumulator
(iterate (- counter 1) (* accumulator counter))))
(if (< number 0)
(princ "неверный аргумент")
(iterate number 1)))
По-хорошему, любой честный интерпретатор лиспа (или его диалектов, скажем scheme) может преобразовать такую рекурсию -- в итерацию (цикл), по-крайней мере, с математической точки зрения они абсолютно одинаковы.
Думайте над оптимизацией, господа.
Ноги, крылья... Главное -- хвост! (c)