2009-08-22 84 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世界的定义和功能里面,甚至没有停下来考虑是否对象被存储为值或引用;但这些可以作为原始对象的替代(不考虑可变性或其他特殊用途)。