Как "минусы" работают в Lisp?
Я изучал Lisp, и у меня нет опыта в программировании Lisp. В части моих исследований я столкнулся с приведенными ниже примерами:
> (cons ‘a ‘(a b)) ----> (A A B)
> (cons ‘(a b) ‘a) ----> ((A B).A)
мне было интересно, почему, когда у нас есть (минусы ' a ‘(a b)) ответ (A A B) и почему, когда мы его немного меняем и ставим ' a после (a b) ответ пунктирная список типа ((A B).А)? В чем разница между первой строкой кода и второй? Что происходит за этими кодами?
4 ответов
это довольно легко понять, если вы думаете о них как минусы-клеток.
короче говоря, ячейка минусов состоит из ровно два значения. Нормальным обозначением для этого является использование точки, например:
(cons 'a 'b) ==> (A . B)
но поскольку списки так часто используются в LISP, лучше обозначить точку.
Списки создаются с помощью второго элемента новой ячейки минусов, с последним окончанием Терминатора (обычно nil или '()
В общем Lisp). Так эти двое равны:--27-->
(cons 'a (cons 'b '())) ==> (A B)
(list 'a 'b) ==> (A B)
так (cons 'a 'b)
создает ячейку [a,b]
и (list 'a 'b)
создать [a, [b, nil]]
. Обратите внимание на соглашение о кодировании списков в ячейках cons: они заканчиваются внутренним nil
.
теперь, если вы против 'a
в последнем списке вы создаете новую ячейку минусов, содержащую [[a, [b, nil]], a]
. Поскольку это не" правильный " список, т. е. он не заканчивается nil
, способ записать это-использовать точку:(cons '(a b) 'a) ==> ((a b) . a)
.
если точка не было напечатано, это должен был быть список со структурой [[a, [b, nil]], [a, nil]]
.
ваш пример
когда вы (cons 'a '(a b))
он будет принимать символ 'a
и список '(a b)
и поместите их в новую ячейку минусов. Таким образом, это будет состоять из [a, [a, [b, nil]]]
. Поскольку это, естественно, заканчивается внутренняя nil
написано без точек.
как (cons '(a b) 'a)
, теперь вы получите [[a, [b, nil]], a]
. Это делает не расторгнуть с внутренним nil
, и поэтому будет использоваться точечная нотация.
можем ли мы использовать минусы, чтобы последний пример заканчивался внутренним нулем? Да, если мы это сделаем
(cons '(a b) (cons 'a '())) ==> ((A B) A)
и, наконец,
(list '(a b) 'a))
эквивалентно
(cons (cons (cons 'a (cons 'b '())) (cons 'a '())))
посмотреть эту визуализацию:
CL-USER 7 > (sdraw:sdraw '(A A B))
[*|*]--->[*|*]--->[*|*]--->NIL
| | |
v v v
A A B
CL-USER 8 > (sdraw:sdraw '((A B) . A))
[*|*]--->A
|
v
[*|*]--->[*|*]--->NIL
| |
v v
A B
также:
CL-USER 9 > (sdraw:sdraw '(A B))
[*|*]--->[*|*]--->NIL
| |
v v
A B
CL-USER 10 > (sdraw:sdraw (cons 'A '(A B)))
[*|*]--->[*|*]--->[*|*]--->NIL
| | |
v v v
A A B
CL-USER 11 > (sdraw:sdraw (cons '(A B) 'A))
[*|*]--->A
|
v
[*|*]--->[*|*]--->NIL
| |
v v
A B
список (A b c) представляется (хранится внутри) как три минусы-ячейки: (cons 'a (cons 'b (cons 'c '())
. Обратите внимание, что последняя пара имеет '() в своем cdr.
серия минусов-ячейки, последний cdr которых ' () печатается в виде списка принтером. Таким образом, пример печатается как (A b c).
давайте посмотрим на: (cons 'a '(a b))
.
список '(a b) представлен как (минусы 'a (минусы 'b' ()). Это означает, что
(cons 'a '(a b))
выдает: (cons 'a (cons 'a (cons 'b '()))
.
давайте посмотрим на: (cons '(a b) 'a)
.
список '(a b) представлен как (минусы 'a (минусы 'b' ()). Это означает, что
(cons (cons '(a b) 'a))
производит (cons (cons 'a (cons 'b '()) 'a)
.
обратите внимание, что эта серия не закончится в '()
. Чтобы показать, что принтер использует точечную нотацию. ( ... . 'a)
означает, что значение состоит из ряда минусов-ячеек и что последний cdr содержит 'a
. Значение (cons (cons 'a (cons 'b '()) 'a)
таким образом печатается как '((a b) . a)
.
A cons
- это структура данных, которая может содержать два значения. Например!--2-->. Первая часть -car
, второй -cdr
. А cons
это list
если это cdr
либо nil
или list
. Таким образом
(1 . (2 . (3 . ())))
список.
при печати cons
точка отсутствует, когда cdr
это cons
или nil
. Внешние скобки cdr
тоже опущен. Таким образом (3 . ())
печати (3)
и (1 . (2 . (3 . ())))
печати (1 2 3)
. То же самое структура, но с другой визуализацией. А cons
на car
не имеет этого правила.
функция read читает cons
с точкой и странным исключительным форматом печати, когда cdr
список. Он будет во время чтения вести себя так, как если бы он был cons
.
С особым правилом для обоих read
и print
иллюзия из списка, даже если это цепи cons
.
(cons ‘a ‘(a b)) ----> (A . (A B))
(cons ‘(a b) ‘a) ----> ((A B) . A)
при печати первым является один список из 3 элементы с cdr
список.