Почему поиск элементов с использованием операций car и cdr вызывает исключение, а (append) - нет? - PullRequest
0 голосов
/ 05 марта 2012

Предположим, я получил этот сегмент кода:

(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). Однако, когда идет рекурсия, во 2-й раз будет '(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 ]

2 голосов
/ 05 марта 2012

(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

Вы видите свою ошибку?

2 голосов
/ 05 марта 2012
;; '(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))

Это не действительный Лисп.

Lisp также не будет "падать". Это просто сигнализирует об ошибке.

SBCL также не является переводчиком. Он использует компилятор.

...