В самом вежливом смысле ваш код немного не в порядке.Ты изучаешь Лисп на этой неделе?Это нормально!Это забавный язык, и он действительно может делать удивительные вещи.
Итак, я собираюсь пройтись по созданию рутины и взять вас с собой в тур.
Ваш основной пример -
(defun negate (n)
(if (> n 0) (- 0 n)))
(map #'negate '(1 2 3 4))
Ходить по дереву сложнее, но давайте разберемся с идеями.
По сути, у вас есть три варианта ответа: текущий элемент - ноль, список или атом?
(if (not (car seq))
(if (listp (car seq))
;;Recurse
;;Otherwise negate the current element and append it to the recursed.
Давайте попробуем сначала сделать следующее:
(defun negate-seq (seq)
(if (not seq)
(return-from negate-seq))
(if (listp (car seq))
(negate-seq seq)
(list (negate (car seq)) (negate-seq (cdr seq)))))
Отлично!Кроме ...
(negate-seq '(1 2)) ==> (-1 (-2 NIL))
И ...
(negate-seq '(1 (1 2 -3))) ==> STACK OVERFLOW!
Ох, мальчик.У нас сейчас проблемы.
Во-первых, давайте просто попробуем cons
вместо list
.Это устраняет странную проблему с вложенными списками.
Очевидно, что мы попали в цикл бесконечной рекурсии.Это не должно быть возможно, потому что у нас охранник not seq
.Хорошо, давайте попробуем отладку.Я использую CLISP и могу отследить аргументы с помощью:
(trace 'negate-seq)
затем,
(negate-seq '(1 (1 2 -3)))
Внезапно я вижу взрыв
1621. Trace: (NEGATE-SEQ '((1 2 -3)))
1622. Trace: (NEGATE-SEQ '((1 2 -3)))
1623. Trace: (NEGATE-SEQ '((1 2 -3)))
1624. Trace: (NEGATE-SEQ '((1 2 -3)))
Crikey,Я забыл свой CDR и составить список дел!Хммммм.
Давайте попробуем это:
(defun negate-seq (seq)
(if (not seq)
(return-from negate-seq))
(if (listp (car seq))
(cons (negate-seq (car seq))
(negate-seq (cdr seq)))
(cons (negate (car seq)) (negate-seq (cdr seq)))))
Рекурсировать машину, отойти в машину, собрать их вместе, мы можем что-то предпринять.
(negate-seq '(1 (1 2 -3))) => (-1 (-1 -2 NIL)
Хммм.Давайте посмотрим на след.
- Trace: (NEGATE-SEQ '(1 (1 2 -3)))
- Trace: (NEGATE-SEQ'((1 2 -3)))
- Трассировка: (NEGATE-SEQ '(1 2 -3))
- Трассировка: (NEGATE-SEQ' (2 -3))
- Трассировка: (NEGATE-SEQ '(-3))
- Трассировка: (NEGATE-SEQ' NIL)
- Трассировка: NEGATE-SEQ ==> NIL
- Трассировка: NEGATE-SEQ ==> (NIL)
- Трассировка: NEGATE-SEQ ==> (-2 NIL)
- Трассировка: NEGATE-SEQ ==> (-1 -2 NIL)
- Трассировка: (NEGATE-SEQ 'NIL)
- Трассировка: NEGATE-SEQ ==> NIL
- Трассировка: NEGATE-SEQ ==> ((-1 -2 ноль))
- Трассировка: NEGATE-SEQ ==> (-1 (-1 -2 ноль))
Так что я повторюсь до -3тогда .... это отваливается?Странный.Ах!Я постоянно хватаю CDR вещей.CDR - это всегда список.(cdr '(-3)) - ноль!
Давайте посмотрим здесь ...
(много копается)
Отрицание возвращает ноль при положительном.D'о.
(defun negate (n)
(if ( > n 0)
(- 0 n)
n))
(defun negate-seq (seq)
"Written by Paul Nathan"
(if (not seq)
(return-from negate-seq))
(if (listp (car seq))
(cons (negate-seq (car seq))
(negate-seq (cdr seq)))
(cons (negate (car seq))
(negate-seq (cdr seq)))))