Неожиданный результат с минусами()
-
28-09-2019 - |
Вопрос
Я имею опыт работы с императивами, но в эти дни пробую свои силы в LISP (Common LISP)
Я читал здесь о нас cons
это
(минусы x L):
Учитывая объект LISP x и список L, вычисление (cons x L) создает список, содержащий x, за которым следуют элементы из L.
Когда я намеренно не использовал список в качестве второго аргумента, т.е. когда я использовал
(cons 'a 'a)
Я ожидал ошибки, но ого!Я получил (A . A)
.
Что я пропустил и что такое (A . A)
?
Решение
Cons
создает "ячейку cons".На первый взгляд, это не имеет никакого отношения к спискам.Ячейка cons - это пара из двух значений.Ячейка cons представлена в письменной форме "парой точек", например (A . B)
, который содержит два значения 'A
и 'B
.
Два места в ячейке cons называются "car" и "cdr".Вы можете визуализировать такую ячейку cons в виде разделенного пополам блока:
car cdr
+-----+-----+
| A | B |
+-----+-----+
В Lisp значение также может быть ссылкой на что-то другое, например, на другую ячейку cons:
+-----+-----+ +-----+-----+
| A | --------> | B | C |
+-----+-----+ +-----+-----+
Это было бы представлено в виде "пунктирной пары" следующим образом (A . (B . C))
.Вы можете продолжать в том же духе:
+-----+-----+ +-----+-----+ +-----+-----+
| A | --------> | B | --------> | C | D |
+-----+-----+ +-----+-----+ +-----+-----+
Это (A . (B . (C . D)))
.Как вы можете видеть, в такой структуре значения всегда находятся в car
ячейки cons, а также cdr
указывает на остальную часть структуры.Исключением является последнее значение, которое находится в последнем cdr
.Однако нам не нужно это исключение:в этом есть особая ценность NIL
в лиспе, который обозначает "ничего".Поставив NIL
в последний cdr
, у вас есть удобное значение sentinel, и ВСЕ ваши ценности заключаются в car
s:
+-----+-----+ +-----+-----+ +-----+-----+ +-----+-----+
| A | --------> | B | --------> | C | --------> | D | NIL |
+-----+-----+ +-----+-----+ +-----+-----+ +-----+-----+
Вот как создается список в Lisp.С тех пор как (A . (B . (C . (D . NIL))))
немного громоздкий, он также может быть представлен просто как (A B C D)
. NIL
также называется пустым списком ()
;это взаимозаменяемые обозначения для одного и того же объекта.
Теперь вы можете понять, почему (cons x list)
возвращает другой список. Cons
просто создает другую ячейку cons с помощью x
в car
и ссылка на list
в cdr
:
+-----+-----+
| X | --------> list
+-----+-----+
и если list
является (A B)
, это работает следующим образом:
+-----+-----+ +-----+-----+ +-----+-----+
| X | --------> | A | --------> | B | NIL |
+-----+-----+ +-----+-----+ +-----+-----+
Итак, (cons x '(a b))
оценивает до (x a b)
.
Списки - это лишь одно из очень распространенных применений ячеек cons.Вы также можете создавать произвольные деревья из ячеек cons, или циклических списков, или вообще любого ориентированного графа.
Другие советы
'a
атом Лисс и (A . A)
это вырожденный список называется Минусы клетки или «пунктирная пара». Так как вы не проходили список для аргумента L
в (cons x L)
Вы вернулись клетку.
(Минусы х л)
Учитывая x и l, минусы возвращает новую минусную клетку с x как автомобиль этой клетки и l в качестве CDR этой клетки.
Списки связаны цепи мировых клеток.
CL-USER 141 > (sdraw '(a b c))
[*|*]--->[*|*]--->[*|*]---> NIL
| | |
v v v
A B C
CL-USER 142 > (sdraw (cons 'foo '(a b c)))
[*|*]--->[*|*]--->[*|*]--->[*|*]---> NIL
| | | |
v v v v
FOO A B C
Если минусы получают два символа в качестве аргумента, похоже на это:
CL-USER 143 > (sdraw (cons 'foo 'bar))
[*|*]---> BAR
|
v
FOO