В упражнении SICP 2.26 с использованием DrScheme, почему cons возвращает список, а не пару списков?
В упражнении SICP 2.26 приведен этот код схемы:
(define x (list 1 2 3))
(define y (list 4 5 6))
Затем передается этот вызов cons:
(cons x y)
Я ожидал, что пара списков вернется, ((1 2 3) (4 5 6))
, но интерпретатор дает,
((1 2 3) 4 5 6)
... список с 4 элементами, первый из которых является списком. Почему вы относитесь к другому? Я попытался найти другие ответы SICP для объяснения, но не смог найти что-то удовлетворительное. Так могут ли эксперты Scheme/ Lisp пролить свет на этот аспект минусов? Заранее благодарим за понимание.
Ответы
Ответ 1
'((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 и dotted-pair, сократите проблему до '(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
Ответ 2
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
, если он представлен в скобках. И это пара списков.
Ответ 3
Я нашел диаграммы в Emacs Lisp учебнике, особенно полезно при обучении Lisp.
Ответ 4
Эй, я думаю, вы могли бы подумать об этом таким образом;
всякий раз, когда есть нуль, должна быть пара скобок, как следует:
(минус 1 (минус 2 ноль)) → (список 1 2)
(пусть ((x (список 1 2 3)) (y (список 4 5 6))))
1. (cons x y) → (cons (cons 1 (cons 2 (cons 3 ноль))) (минус 4 (минус 5 (минус 6 ноль))))
здесь первый ниль обозначает конец пары, который может быть выражен скобкой; тогда как второй ниль означает конец всей пары, который использует другую пару круглых скобок;
так, ((1 2 3) 4 5 6)
2. (list x y) → (cons x (cons y nil);
поскольку мы знаем, что x содержит nil, поэтому оно должно быть (1 2 3); вторая часть содержит два низа,
поэтому ((1 2 3) (4 5 6));
внутреннее большинство nil означает внешнюю большую скобку;
Надеюсь, это поможет.
Ответ 5
Прочтите следующее: http://en.wikipedia.org/wiki/Cons
Ответ 6
попробуйте (список x y)
Я уверен, что он работает с общим lisp, я не знаю о Scheme