Я начал изучать Схему для забавы главным образом, и потому что я никогда не использовал функциональный язык прежде. Я выбрал Scheme, потому что я хотел считать SICP в течение долгого времени.
Так или иначе я в настоящее время узнаю о списках, и прежде который я узнал о недостатках, автомобиле и CDR. И существует пример, который создает список списков с недостатками, как это:
(cons (list 1 2) (list 3 4))
Получающийся список ((1 2) 3 4), который не имеет смысла мне, я ожидал бы ((1 2) (3 4)) быть результатом (список, вошедший из двух списков). Почему это ведет себя как этот? Я понимаю, что, если бы я должен был использовать автомобиль, я добрался бы (1 2), и CDR, я получил бы (3 4) becaue CDR всегда, возвращает "остальных", но я не понимаю, почему в список не входят двух списков?
Вы получаете список с (1 2)
в качестве первого элемента (car) и (3 4)
в качестве остальных (cdr), потому что первый аргумент cons - первый элемент списка, а второй аргумент - список, содержащий остальные элементы.
Это очень напоминает структуру списка: каждый узел (правильного) списка содержит элемент и список, содержащий все остальные элементы. cons
создает один такой узел.
Если второй аргумент cons
станет вторым элементом списка, то как создать список с тремя аргументами? Пришлось бы сделать cons
переменным, и тогда это было бы просто другое имя для list
.
Если вы хотите создать список списков, используйте (list (list (list 1 2) (list 3 4))
.
(list (list 1 2)
(list 3 4))
это то же самое, что
(cons (list 1 2)
(cons (list 3 4)
'()))
что приводит к
((1 2) (3 4))
что также можно записать как
((1 . (2 . ()))
.
((3 . (4 . ()))
.
()))
list A: [ | ]
1 [ | ]
2 /
list B: [ | ]
3 [ | ]
4 /
======================
(cons A B)
[ | ]
[ | ] [ | ]
1 [ | ] 3 [ | ]
2 / 4 /
Графическое представление внутренних структур может помочь нам визуализировать проблему.
И это еще немного поможет:
[ | ]
X [ | ]
3 [ | ]
4 /
Вы видите образец? Выше приведен список (X 3 4)
. По этой причине (cons A B)
рисует только часть car
как отдельный список, а не cdr
.
Поскольку конс-ячейка - это не список из двух элементов, эти два понятия часто путают. Если (a . b)
является конс-ячейкой, то (a . (b . ()))
- это список из двух элементов. Любой список, безопасный конкретно для пустого списка, является cons-ячейкой, поле car которой содержит первый элемент, а поле cdr - список, содержащий остальные элементы. Таким образом, список - это просто двоичное дерево, крайним правым листом которого является специальная константа ()
или nil
в зависимости от вашего диалекта.
Вот почему (cons 0 '(1 2 3))
оценивается в (0 1 2 3)
, а не в (0 (1 2 3))
Мы создаем ячейку cons, чьим car является 0
, а cdr - (1 2 3)
, поэтому список (0 1 2 3)
.