"Cons"如何在Lisp中运行?

Ami*_*ard 11 lisp common-lisp cons

我正在学习Lisp,我对Lisp编程没有经验.在我的部分学习中,我遇到了以下例子:

> (cons ‘a ‘(a b))  ----> (A A B)
> (cons ‘(a b) ‘a)  ----> ((A B).A)
Run Code Online (Sandbox Code Playgroud)

我想知道为什么当我们(cons'a'(ab))时,响应是(AAB),为什么当我们稍微改变它并把'a after (ab)时,响应是一个虚线列表就像((AB) ).A)?第一个代码行和第二个代码行有什么区别?这些代码背后发生了什么?

csl*_*csl 13

如果您将它们视为缺点,那么很容易理解.

总之,一个cons单元包含恰好两个值.对此的常规表示法是使用点,例如:

(cons 'a 'b) ==> (A . B)
Run Code Online (Sandbox Code Playgroud)

但由于列表在LISP中经常使用,因此更好的方法是删除点.列表是通过使第二个元素成为新的cons单元格,最后结束终止符(通常为nil,或者'()在Common Lisp中).所以这两个是平等的:

(cons 'a (cons 'b '())) ==> (A B)
(list 'a 'b) ==> (A B)
Run Code Online (Sandbox Code Playgroud)

因此(cons 'a 'b)创建一个单元格[a,b],(list 'a 'b)并将创建[a, [b, nil]].注意在cons单元格中编码列表的约定:它们以内部结束nil.

现在,如果您查看'a最后一个列表,则创建一个包含的新增量单元格[[a, [b, nil]], a].因为这不是一个"正确的"列表,即它不是以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来使最后一个示例以内部nil结束吗?是的,如果我们这样做

(cons '(a b) (cons 'a '())) ==> ((A B) A)
Run Code Online (Sandbox Code Playgroud)

最后,

(list '(a b) 'a))
Run Code Online (Sandbox Code Playgroud)

相当于

(cons (cons (cons 'a (cons 'b '())) (cons 'a '())))
Run Code Online (Sandbox Code Playgroud)


Rai*_*wig 6

看到这个可视化:

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
Run Code Online (Sandbox Code Playgroud)

也:

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
Run Code Online (Sandbox Code Playgroud)


Syl*_*ter 5

Acons是可以包含两个值的数据结构。例如(cons 1 2) ; ==> (1 . 2)。第一部分是car,第二部分是cdr。如果Acons是或a ,则 A 是 a 。因此\nlistcdrnillist(1 . (2 . (3 . ())))是一个列表。

\n\n

打印时,如果是 a或 ,cons则省略点。the 的外括号也被省略。如此打印并打印。它具有相同的结构,但具有不同的可视化效果。一个在cdrconsnilcdr(3 . ())(3)(1 . (2 . (3 . ())))(1 2 3)conscar没有这个规则。

\n\n

当列表是一个列表时,读取函数cons以点和奇怪的异常打印格式读取cdr。它在读取时的行为就像是一样cons

\n\n

通过对两者都有特殊的规则,read即使print列表是链式的,列表的幻觉也是完整的cons

\n\n
(cons \xe2\x80\x98a \xe2\x80\x98(a b))  ----> (A . (A B)) \n(cons \xe2\x80\x98(a b) \xe2\x80\x98a)  ----> ((A B) . A)\n
Run Code Online (Sandbox Code Playgroud)\n\n

打印时,第一个是 3 个元素的列表,因为它cdr是一个列表。

\n