Почему поиск элементов с использованием операций car и cdr вызывает исключение, а (append) - нет?
Предположим, я получил этот сегмент кода:
(defparameter *islands* '((1 9 8 5) (6 4 2 3)))
(defun edge-pair (a b)
(unless (eql a b)
(list (cons a b) (cons b a))))
(defun connected-with-bridges (islands)
(when (cdr islands)
(append (edge-pair (caar islands) (caadr islands))
(connected-with-bridges (cdr islands)))))
Теперь, если я передаю переводчик (SBCL):
(connected-with-bridges '((1 9 8 5) (6 4 2 3)))
Результат:
((1 . 6) (6 . 1))
Это не потерпит крах. Однако, если я пройду:
;; '(6 4 2 3) is actually (cdr '((1 9 8 5) (6 4 2 3)))
(caar '(6 4 2 3))
Это потерпит крах. В соответствии с (connected-with-bridges)
функция, cdr списка *islands*
будет продолжаться до тех пор, пока не сможет продолжить. Первый раз когда *islands*
передается в (connected-with-bridges)
, список будет '((1 9 8 5) (6 4 2 3)
, Тем не менее, как рекурсия идет, второй раз будет '(6 4 2 3)
который в (append)
Функция будет иметь:
(append (edge-pair (caar '(6 4 2 3)) (caadr '(6 4 2 3)))
(connected-with-bridges (cdr islands)))
Это, очевидно, сбой, если я запускаю его в интерпретаторе в одиночку, но не с, если он запускается внутри (append)
, который находится внутри (соединен с мостами).
2 ответа
(caar '(6 4 2 3))
сигнализирует об ошибке, потому что вы пытаетесь сделать (car 6)
и 6 это не список.
Внутри вашей функции у вас нет (caar '(6 4 2 3)), но(caar '((6 4 2 3)))
,
Посмотрите, как работает CDR:(cdr '((1 9 8 5) (6 4 2 3))))
=> '((6 4 2 3))
не '(6 4 2 3)
Итак...
(caar '((6 4 2 3))) => 6, и (car '(6 4 2 3))
=> 6
Вы видите свою ошибку?
;; '(6 4 2 3) is actually (cdr '((1 9 8 5) (6 4 2 3)))
Нет. Попробуй это.
(caar '(6 4 2 3) (caadr '(6 4 2 3))
Это не действительный Лисп.
Лисп тоже не будет "падать". Это просто сигнализирует об ошибке.
SBCL также не является переводчиком. Он использует компилятор.