2009-08-22 56 views
11

Common Lisp Cons Cell的定義究竟是什麼? Cons Cell與標準鏈表項目有何不同?畢竟,cons單元格和鏈接列表項都有一個值和一個指向下一個單元格或項目的指針......或者這種理解是否錯誤?什麼是Lisp Cons Cell的定義?

+1

每一個列表(除了'nil')都是一個cons單元,但不是每個單元格都是一個列表(如果它的'cdr'不是一個列表) – mihi 2009-08-22 21:31:33

+2

我只是想澄清一下,我在比較一個Common Lisp列表及其缺點單元格,以及像C,C++或Java這樣的語言實現的常規可見列表及其項目。 – 2009-08-22 23:26:57

回答

19

Cons單元通常擁有兩個指針,可以指向任何東西。一般用法當然是指向左邊的一個「值」,另一個是「右邊」的另一個Cons單元(或零)。

+7

cons cell也可以直接保存值,而不需要指針。由(cons 1 2)製作的交流單元將有指向數字的指針,但可以直接存儲它們(對於其他一些小型項目(如字符)也是如此)。 – 2009-08-23 07:23:45

+0

將不會有指向數字的指針,我的意思是 – 2009-08-23 07:24:24

13

cons單元比鏈表節點更接近二叉樹節點。 car和cdr返回兩個孩子,可以是零,原子或其他的缺陷細胞。

+7

爲了強調這裏的區別,沒有要求第二個元素必須是另一個cons單元。 ('豆腐1)'是一個有效的反應池。 – Chuck 2009-08-22 21:18:48

7

在Lisp中,cons單元包含一對值。如果單元格位於變量c中,則(car c)返回第一個值,(cdr c)返回第二個值。

按照慣例,一個列表由cons單元格組成,其中單元格的car包含節點值,並且cdr包含對下一個節點的引用或nil(空列表)以指示列表的結尾。當原語函數返回或接受列表時,這是呈現列表的格式。

因此,對於該列表l(car l)給人的第一元件(在第一cons單元的值)和(cdr l)返回列表的尾部(在列表中的下一cons單元)。

3

我認爲這裏的其他答案雖然準確,但對一件事並不明確。

在傳統的C++鏈表實現中,兩個字段(valnext,例如)是,其類型爲next定義爲指向列表中的另一個節點,其中null是終結符。你不能指向任何東西,但另一個節點next

的Lisp是動態類型,所以,在cons單元或者字段可以是任何(無論是一個原子或一參考)。你可以用cons單元實現一個鏈表(這是一個Lisp列表:一個帶有終止符的nil的cons單元鏈),但是你也可以在每個字段中使用一個cons單元作爲座標對,一棵樹節點等

你甚至可以結合這些;例如,的xy座標的列表:

;; (cons foo (cons bar nil)) == (list foo bar)  
(cons 
    (cons 5 4) 
    (cons (cons 9 10) nil)) 
=> 
((5 . 4) (9 . 10)) 

甲cons單元因此嚴格大於一個鏈接列表節點更一般;它更接近於「應用對」,可以這麼說。所有標準列表處理函數(map,dolist等)都是假設的簡單函數,您將值放入car中,並將其他列表放入cdr中。

這一切都意味着 - 如果你想 - 你可以定義列表向後,用car指向下一個利弊細胞和cdr指向的值!要做到這一點與鏈表節點,你必須重新定義類或數據結構來改變類型。

4

A cons單元格是由cons,carcdr組成的合同的三分之一,其要求如同其他人所提及的那樣,它們表現爲配對。

從這個定義中刪除「參考」,「指針」等詞語的原因是要認識到這些是實現細節。如果你願意,你可以建立一個cons憑空作爲阿伯爾森和薩斯曼做的:

(define (cons a b) (lambda (x) (x a b))) 
(define (car x) (x (lambda (a b) a))) 
(define (cdr x) (x (lambda (a b) b))) 

這個定義完全是生活的Lisp世界的定義和功能裏面,甚至沒有停下來考慮是否對象被存儲爲值或引用;但這些可以作爲原始對象的替代(不考慮可變性或其他特殊用途)。