cons()的意外输出

时间:2010-08-14 06:55:17

标签: lisp common-lisp cons

我来自一个势在必行的背景,但这些天我在LISP上尝试(普通LISP)

我读了here 关于cons

的内容
  

(cons x L):

  给定LISP对象x和列表L,求值(cons x L)创建一个包含x的列表,后跟L中的元素。

当我故意不使用列表作为第二个参数时,即当我使用

(cons 'a 'a)我预计会出错,但哇!我得到了(A . A)

我错过了什么,(A . A)是什么?

3 个答案:

答案 0 :(得分:7)

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)))。如您所见,在这样的结构中,值始终位于cons单元格的car中,而cdr指向结构的其余部分。最后一个值是最后一个cdr。但是我们不需要这个例外:Lisp中有一个特殊值NIL,表示“无”。通过将NIL放入最后cdr,您有一个方便的哨兵值,并且所有您的值都在car s中:

+-----+-----+       +-----+-----+       +-----+-----+       +-----+-----+
|  A  |   --------> |  B  |   --------> |  C  |   --------> |  D  | NIL |
+-----+-----+       +-----+-----+       +-----+-----+       +-----+-----+

这是在Lisp中构建列表的方式。由于(A . (B . (C . (D . NIL))))有点笨拙,因此它也可以简单地表示为(A B C D)NIL也称为空列表();这些是同一事物的可更换符号。

现在您可以看到为什么(cons x list)会返回另一个列表。 Cons只需在x中构建另一个包含car的增量内容单元,在list中引用cdr

+-----+-----+
|  X  |   --------> list
+-----+-----+

如果list(A B),则表示为:

+-----+-----+       +-----+-----+       +-----+-----+
|  X  |   --------> |  A  |   --------> |  B  | NIL |
+-----+-----+       +-----+-----+       +-----+-----+

因此,(cons x '(a b))评估为(x a b)

列表只是cons细胞的一种常见用法。您还可以从cons单元格,圆形列表或任何有向图形构造任意树。实际上。

答案 1 :(得分:1)

'a是一个lisp原子,(A . A)是一个简并列表,称为cons cell或“点对”。由于您没有在L中传递参数(cons x L)的列表,因此您返回了一个单元格。

答案 2 :(得分:1)

(CONS x L)

给定x和L,CONS返回一个新的cons单元格,x为该单元格的CAR,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

如果CONS将两个符号作为参数,它看起来像这样:

CL-USER 143 > (sdraw (cons 'foo 'bar))

[*|*]---> BAR
  |
  v
 FOO