В упражнении 2.26 SICP дан этот код Схемы:
(define x (list 1 2 3))
(define y (list 4 5 6))
Затем это подставляет вызов, дан:
(cons x y)
Я ожидал, что пара списков закончится, ((1 2 3) (4 5 6))
но интерпретатор дает, ((1 2 3) 4 5 6)
... список с 4 элементами, при этом первым является список. Почему y рассматривают по-другому? Я попытался искать другие ответы SICP для объяснения, но не мог найти что-то удовлетворительным. Таким образом, какие-либо эксперты по Схеме/Lisp могли пролить некоторый свет на этот аспект недостатков? Заранее спасибо за любое понимание.
'((1 2 3) 4 5 6)
на самом деле представляет собой пару списков. Вот другой способ записать это:
'((1 2 3) . (4 5 6))
Однако принтер по возможности избегает обозначения пар из точек, поэтому вместо этого вы получаете первое представление. Правило:
'(x . (xs ...))
=>
'(x xs ...)
Для любых x
и xs
. Здесь ваши x = '(1 2 3)
и xs =' (4 5 6)
, поэтому вы получаете ((1 2 3) 4 5 6)
.
Чтобы увидеть, как связаны cons и точечная пара, давайте сократим задачу до '(1)
и ' (6)
. На самом низком уровне можно построить пару из них:
(cons (cons 1 '()) (cons 6 '()))
Здесь '()
равно нулю или пустому списку. Если мы переведем это буквально в нотацию с точечной парой, мы получим следующее:
'((1 . ()) . (6 . ()))
Но поскольку принтер сворачивает нотацию с точечной парой, когда это возможно, вы получаете вместо этого следующее:
'((1 . ()) . (6 . ()))
=>
'((1) . (6)) ; <-- x=1, xs=nothing; x=6, xs=nothing
=>
'((1) 6) ; <-- x=1, xs=6
cons
использует первый аргумент как заголовок списка, а второй как хвост.
Вы даете ему первый список (1 2 3)
, который будет составлять заголовок результирующего списка, и второй список (4 5 6)
, который будет использоваться в качестве хвост списка. Таким образом, вы заканчиваете на ((1 2 3) 4 5 6)
.
Списки в виде гребешков слева направо, заканчивающиеся пустым списком (здесь представлены как o
), и посмотрите, как они сочетаются.
X= Y=
/\ /\
1 /\ + 4 /\
2 /\ 5 /\
3 o 6 o
Затем вы строите:
/\
X Y
Получение:
/\
/\ \
1 /\ \
2 /\ \
3 o/\
4 /\
5 /\
6 o
что есть ((1 2 3) 4 5 6
в скобках. И это пара списков.
try (list x y) Я уверен, что это работает на common lisp, я не знаю о Scheme
Я обнаружил, что диаграммы в учебнике Emacs Lisp особенно полезны при изучении Lisp.