ANSI Common Lisp 笔记二(列表)

摘自 《ANSI Common Lisp》

一、构建

cons函数可以用于构建列表,如:

CL-USER> (cons 'a 'b)
(A . B)
CL-USER> (cons 'a '(1 2 3))
(A 1 2 3)
CL-USER> 


cons真正所做的事情是,把两个对象结合成一个有两部分的对象,称之为 Cons 对象。概念上来说,一个 Cons是一对指针;第一个是car,第二个是cdr。

列表可以嵌套,称为嵌套列表,如:

CL-USER> (cons '(a b c) '(1 2 3))
((A B C) 1 2 3)

而类似 (A 1 2 3) 则称为 平坦列表(flatlist)。


所有不是Cons 对象的东西,就是一个原子(atom)。注意:nil 即是一个原子也是一个列表。


二、等式

每一次调用cons ,Lisp会配置一块新的内存给两个指针。所以如果用同样的参数调用两次cons,实际上得到的是两个不同的对象。

CL-USER> (eql (cons 'a nil) (cons 'a nil))
NIL

eql只有在两个对象是同一个对象时才返回为真。而equal在参数值相同时返回真。


三、映射函数

Common Lisp 提供了数个函数来对一个列表的元素做函数调用。最常使用的是mapcar,接受一个函数以及一个或多个列表,并返回把函数应用至每个列表的元素的结果,直到有的列表没有元素为止:

CL-USER> (mapcar #' (lambda (x) (+ x 1))
   '( 1 2 3))
(2 3 4)

CL-USER> (mapcar #' list '(a b c) '(1 2 3 4))
((A 1) (B 2) (C 3))


maplist 接受同样的参数,将列表的渐进的下一个cdr 传入参数。

CL-USER> (maplist #' (lambda (x) x)
    '(a b c))
((A B C) (B C) (C))


四、集合

member方法,返回指定的列表中指定的元素开始的部分。例如:

CL-USER> (member 'a '(a b c))
(A B C)
CL-USER> (member '2 '(1 2 3 4 5 6))
(2 3 4 5 6)


一般情况下,member使用 eql 来比较对象。你可以使用一种叫做关键字参数的东西来重写缺省的比较方法。多数的 Common Lisp 函数接受一个或多个关键字参数。这些关键字参数不同的地方是,他们不是把对应的参数放在特定的位置作匹配,而是在函数调用中用特殊标签,称为关键字,来作匹配。一个关键字是一个前面有冒号的符号。一个member函数所接受的关键字参数是 :test参数。如果你在调用member时,传入某个函数作为:test参数,那么那个函数就会被用来比较是否相等,而不是用 eql。所以如果我们想找到一个给定的对象与列表中的成员是否相等(equal),我们可以:
>   (member  ' ( a )   ' ( ( a )   ( z ) )   :test   # ' equal)
( ( A )   ( Z ) )


另一个member接受的关键字参数是:key参数。借由提供这个参数,你可以在作比较之前,指定一个函数运用在每一个元素:
>(member   ' a   ' ((a b)   (c d))  :key   # ' car)
(( A   B)   (C   D))
在这个例子里,我们询问是否有一个元素的car是a 


如果我们想要找到一个元素满足任意的判断式像是──oddp  ,奇数返回真──我们可以使用相关的member-if:
>(member-if   #'  oddp   '(2 3 4))
(3 4)


函数adjoin像是条件式的 cons。它接受一个对象及一个列表,如果对象还不是列表的成员,才构建对象至列表上。


集合论中的并集  (union)、交集(intersection)以及补集(complement)的实现,是由函数union、intersection以及set-difference。


五、点状列表(Dotted Lists)

调用list所构建的列表,准确的说称之为正规列表(properlist)。一个正规列表可以是nil 或是cdr是正规列表的 Cons 对象。

一个非正规列表的 Cons 对象称之为点状列表  (dotted list)。如:

CL-USER> (cons 'a 'b)
(A . B)


六、关联列表

用 Cons 对象来表示映射  (mapping)也是很自然的。一个由 Cons 对象组成的列表称之为关联列表(assoc-list or  alist)。这样的列表可以表示一个翻译的集合,举例来说:
CL-USER> (setf trans '((+ . "add") (- . "subtract")))
((+ . "add") (- . "subtract"))

assoc用来取出在关联列表中,与给定的键值有关联的 Cons 对:
CL-USER> (assoc '+ trans)
(+ . "add")







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章