Lisp cons()的意外输出
我来自一个命令式的背景,但这些天我在尝试LISP(Common LISP) 我读到了关于cons (cons x L):Lisp cons()的意外输出,lisp,common-lisp,cons,Lisp,Common Lisp,Cons,我来自一个命令式的背景,但这些天我在尝试LISP(Common LISP) 我读到了关于cons (cons x L): 给定一个LISP对象x和一个列表L,求值(cons x L)将创建一个包含x的列表,后跟L中的元素 当我故意不使用列表作为第二个参数时,即当我使用 (cons'a'a)我以为会出错,但哇!我得到了(A.A) 我错过了什么,什么是(A.A)?'A是一个lisp原子,(A.A)是一个称为或“点对”的退化列表。由于您没有在(cons x L)中传递参数L的列表,因此返回了一个单元格
给定一个LISP对象x和一个列表L,求值(cons x L)将创建一个包含x的列表,后跟L中的元素 当我故意不使用列表作为第二个参数时,即当我使用
(cons'a'a)
我以为会出错,但哇!我得到了(A.A)
我错过了什么,什么是
(A.A)
?'A
是一个lisp原子,(A.A)
是一个称为或“点对”的退化列表。由于您没有在(cons x L)
中传递参数L
的列表,因此返回了一个单元格。(cons x L)
给定x和L,CONS返回一个新的CONS单元,x作为该单元的CAR,L作为该单元的CDR
列表是cons单元格的链接链
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
如果CONS获得两个符号作为参数,则如下所示:
CL-USER 143 > (sdraw (cons 'foo 'bar))
[*|*]---> BAR
|
v
FOO
+-----+-----+ +-----+-----+ +-----+-----+
| A | --------> | B | --------> | C | D |
+-----+-----+ +-----+-----+ +-----+-----+
Cons
构造一个“Cons单元”。起初,这与列表无关。cons单元格是由两个值组成的一对。cons单元格以书面形式由“点对”表示,例如(A.B)
,它包含两个值'A
和'B
cons单元中的两个位置称为“car”和“cdr”。可以将此类cons单元可视化为对分块:
car cdr
+-----+-----+
| A | B |
+-----+-----+
在Lisp中,值也可以是对其他内容的引用,例如,另一个cons单元格:
+-----+-----+ +-----+-----+
| A | --------> | B | C |
+-----+-----+ +-----+-----+
这将以“点对”形式表示为(A.(B.C))
。您可以这样继续:
CL-USER 143 > (sdraw (cons 'foo 'bar))
[*|*]---> BAR
|
v
FOO
+-----+-----+ +-----+-----+ +-----+-----+
| A | --------> | B | --------> | C | D |
+-----+-----+ +-----+-----+ +-----+-----+
这是(A.(B.(C.D))
。如您所见,在这种结构中,值始终位于cons单元格的car
中,cdr
指向结构的其余部分。例外情况是最后一个值,它位于最后一个cdr
中。不过,我们不需要这个异常:在Lisp中有一个特殊的值NIL
,表示“nothing”。通过将NIL
放入最后一个cdr
,您就有了一个方便的哨兵值,并且您的所有值都在车中
s:
+-----+-----+ +-----+-----+ +-----+-----+ +-----+-----+
| A | --------> | B | --------> | C | --------> | D | NIL |
+-----+-----+ +-----+-----+ +-----+-----+ +-----+-----+
这就是Lisp中列表的构造方式。由于(A.(B.(C.(D.NIL))
有点笨拙,它也可以简单地表示为(A.B.C.D)
NIL
也称为空列表()
;这些是相同事物的可交换符号
现在您可以看到为什么(cons x list)
返回另一个列表Cons
只需在car
中用x
和cdr
中对列表的引用构造另一个Cons单元格:
+-----+-----+
| X | --------> list
+-----+-----+
如果列表
是(A B)
,则其计算结果如下:
+-----+-----+ +-----+-----+ +-----+-----+
| X | --------> | A | --------> | B | NIL |
+-----+-----+ +-----+-----+ +-----+-----+
因此,(cons x'(ab))
的计算结果为(xab)
列表只是cons单元格的一个非常常见的用途。实际上,您还可以从cons单元格、循环列表或任何有向图构造任意树