Как "минусы" работают в 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 список.