要理解List关键在于理解构建它的更原始的数据类型,即cons cell。可以通过函数CONS创建它们。
CONS函数需要两个参数,并返回一个新的包含这两个参数的cons cell。CONS的参数可以引用任何类型的数据对象。除第二个参数为NIL或其他cons cell的情况,CONS返回的新的cons cell中的两个值被一个点号所隔开,这样的cons cell被叫做dotted pair。
(cons 1 2) -> (1 . 2)
在一个cons cell中,其第一个值被叫做CAR,第二个值被叫做CDR。
(car (cons 1 2)) -> 1
(cdr (cons 1 2)) -> 2
可以通过SETF来设定CAR或CDR的值。
List就是由一些列被链接在一条链上的cons cell构建的。
(cons 1 nil) ; 等价于(list 1)
(cons 1 (cons 2 nil)) ; 等价于(list 1 2)
(cons 1 (cons 2 (cons 3 nil))) ; 等价于(list 1 2 3)
由上面的例子可以看出,要创建一个类似于(1 2 3)这样的list,使用cons需要关心cons cell链上的每个cons cell细节,比较繁琐,这时可以使用函数LIST来代替CONS。
一个较为复杂的List如下:
(list "foo" (list 1 2) 10) -> ("FOO" (1 2) 10)
可以通过下图来表示上述例子的结构:
"Destructive"操作
由于Lisp的功能传统,修改存在对象的操作被叫做"Destructive"。对于state-modifying操作来说,又可分为for-side-effect和recycling两种截然不同的操作类型。
List操作函数
函数名 | 描述 |
LAST | 返回list中最后一个cons cell,如果带有参数N(整数),则返回最后N个cons cell。 |
BUTLAST | 返回一个list的copy,这个copy不包含list中的最后一个cons cell。如果带有参数N(整数),则copy不包含最后N个cells。 |
NBUTLAST | BUTLAST的recycling版本, |
LDIFF | 返回给定cons cell的一个copy |
TAILP | 判断一个给定对象是否是指定list的tail。 |
LIST* | Builds a list to hold all but the last of its arguments and then makes the last argument the CDR of the last cell in the list. In other words, a cross between LIST and APPEND. |
MAKE-LIST | Builds an n item list. The initial elements of the list are NIL or the value specified with the :initial-element keyword argument. |
REVAPPEND | Combination of REVERSE and APPEND; reverses first argument as with REVERSE and then appends the second argument. |
NRECONC | Recycling version of REVAPPEND ; reverses first argument as if by NREVERSE and then appends the second argument. No reliable side effects. |
CONSP | Predicate to test whether an object is a cons cell |
ATOM | Predicate to test whether an object is not a cons cell |
LISTP | Predicate to test whether an object is either a cons cell or NIL |
NULL | Predicate to test whether an object is NIL. Functionally equivalent to NOT but stylistically preferable when testing for an empty list as opposed to boolean false. |