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")







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