Почему поиск элементов с использованием операций 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 также не является переводчиком. Он использует компилятор.

Другие вопросы по тегам