Сначала алгоритм
Кажется, вы понимаете принцип этого. Рекурсивная итерация по списку - очень распространенная идиома, это Lisp: вы берете список, делаете что-то с FIRST
, а затем вызываете себя с REST
(CAR
/ CDR
- это устаревшие имена, я предпочитаю использовать больше значимые, когда это возможно).
(defun print-every (objects)
(print (first objects))
(print-every (rest objects)))
Когда вы рекурсивны, единственное, что вам нужно, это где-то завершиться, обычно, когда переданный вам список является пустым списком (будьте осторожны, (rest '())
⇒ ()
, поэтому, если функция просто рекурсивно обращается к остальным списка, он никогда не остановится).
(defun print-every (objects)
(when objects
(print (first objects))
(print-every (rest objects))))
Если вам нужно собрать результат из всей операции, обычный способ сделать это - использовать аккумулятор , аргумент функции, который накапливает этот результат.
(defun add-every (numbers &optional sum)
(if numbers
(add-every (rest numbers (+ (first numbers) sum))
sum))
Во-вторых, синтаксис
Как и с любым другим языком программирования, вам нужно быть очень осторожным и не использовать что-то из языка A на языке B.
Аргумент, начинающийся с тире, например -t
, - это то, что вы увидите в bash, а не в Лиспе. (format t "foo")
напечатает foo
(и разрыв строки).
В Лиспе (foo bar(1 2) 3)
будет НЕ передавать аргументы 1
и 2
функции bar
. Если вы хотите, ваш код должен быть (foo (bar 1 2) 3)
.
Кроме того, в Лиспе, какие отдельные выражения являются круглыми скобками и пробелами. Таким образом, '(pro)
- это список, содержащий ONE символ, а '(p r o)
- список, содержащий THREE символов.