Cons 对象提供了一个方便的表示法,来表示任何类型的对象。一个 Cons 对象里的一对指针,可以指向任何类型的对象,包括 Cons 对象本身。它利用到我们之后可以用 cons 来构造列表的可能性。

    我们往往不会把列表想成是成对的,但它们可以这样被定义。任何非空的列表,都可以被视为一对由列表第一个元素及列表其余元素所组成的列表。 Lisp 列表体现了这个概念。我们使用 Cons 的一半来指向列表的第一个元素,然后用另一半指向列表其余的元素(可能是别的 Consnil )。 Lisp 的惯例是使用 car 代表列表的第一个元素,而用 cdr 代表列表的其余的元素。所以现在 car 是列表的第一个元素的同义词,而 cdr 是列表的其余的元素的同义词。列表不是不同的对象,而是像 Cons 这样的方式连结起来。

    当我们想在 上面建立东西时,

    图 3.1 一个元素的列表

    1. > (car x)
    2. A
    3. NIL

    当我们构造一个多元素的列表时,我们得到一串 Cons (a chain of conses):

    产生的结构见图 3.2。现在当我们想得到列表的 cdr 时,它是一个两个元素的列表。

    ../_images/Figure-3.2.png

    图 3.2 三个元素的列表

    1. > (cdr y)

    在一个有多个元素的列表中, 指针让你取得元素,而 cdr 让你取得列表内其余的东西。

    当这种情况发生时,它的结构如图 3.3 所示;第二个 Conscar 指针也指向一个列表:

    1. > (car (cdr z))
    2. (B C)

    图 3.3 嵌套列表

    前两个我们构造的列表都有三个元素;只不过 z 列表的第二个元素也刚好是一个列表。像这样的列表称为嵌套列表,而像 y 这样的列表称之为平坦列表 (flatlist)。

    如果参数是一个 Cons 对象,函数 consp 返回真。所以我们可以这样定义 listp :

      注意, nil 既是一个原子,也是一个列表。