Lisp Cons单元格的定义是什么?

Lisp Cons单元格的定义是什么?,lisp,linked-list,common-lisp,Lisp,Linked List,Common Lisp,公共Lisp Cons单元格的定义到底是什么?Cons单元格与标准链表项有何不同?毕竟,cons单元格和链表项都有一个值和指向下一个单元格或项的指针。。。或者这种理解是错误的?Cons单元格通常有两个指针,可以指向任何东西。通常的用法当然是用左边的一个指向一个“值”,用右边的一个指向另一个Cons单元格(或nil)。Cons单元格比链表节点更接近二叉树节点。car和cdr返回两个子项,可以是nil、atoms或其他cons单元格。在Lisp中,cons单元格包含一对值。如果cons单元格位于变量

公共Lisp Cons单元格的定义到底是什么?Cons单元格与标准链表项有何不同?毕竟,cons单元格和链表项都有一个值和指向下一个单元格或项的指针。。。或者这种理解是错误的?

Cons单元格通常有两个指针,可以指向任何东西。通常的用法当然是用左边的一个指向一个“值”,用右边的一个指向另一个Cons单元格(或nil)。

Cons单元格比链表节点更接近二叉树节点。car和cdr返回两个子项,可以是nil、atoms或其他cons单元格。

在Lisp中,cons单元格包含一对值。如果cons单元格位于变量
c
中,则
(car c)
返回第一个值,而
(cdr c)
返回第二个值

按照惯例,列表由cons单元格组成,其中单元格的
car
包含节点值,
cdr
包含对下一个节点的引用或nil(空列表)以指示列表的结束。当基元函数返回或接受列表时,这是列表的显示格式


因此,对于列表
l
(car l)
给出第一个元素(第一个cons单元格中的值),
(cdr l)
返回列表的尾部(列表中的下一个cons单元格)。

我认为这里的其他答案虽然准确,但没有明确说明一件事

在传统的C++链表实现中,两个字段(<代码> Val< /Calp>和 NeX//Cord>,即)被键入。code>next定义为指向列表中的另一个节点,

null
作为终止符。只能用
next
指向另一个节点

Lisp是动态类型的,所以cons单元格中的任何字段都可以是任何内容(原子或引用)。您可以使用cons单元格实现一个链表(Lisp列表就是:一个cons单元格链,带有
nil
终止符),但您也可以将cons单元格用作坐标对、树节点等,在每个字段中放置任意值

你甚至可以把这些结合起来;e、 例如,
x
y
坐标列表:

;; (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
指向下一个cons单元格,
cdr
指向该值!要使用链表节点做到这一点,您必须重新定义类或数据结构以改变类型。

一个
cons
单元格是由
cons
car
cdr
组成的契约的三分之一,要求它们成对运行,正如其他人所提到的那样

从该定义中省略“引用”、“指针”等词的原因是要认识到这些是实现细节。如果你愿意,你可以像Abelson和Sussman那样,用稀薄的空气建造一个
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定义和功能的世界中,甚至不停下来考虑对象是否被存储为值或引用;然而,这些元素可以作为原始对象的替代品(不考虑易变性或其他特殊用途)。

为了强调这里的区别,不要求第二个元素必须是另一个cons单元格
('tofu.1)
是一个有效的cons单元格。每个列表(除了
nil
)都是一个cons单元格,但不是每个cons单元格都是一个列表(如果它的
cdr
不是一个列表),我只是想澄清一下,我在上面比较的是一个普通的Lisp列表和它的cons单元格,以及一个常规的Lisnked列表和它在C语言中实现的项,C++或Java.cons单元也可以直接保存值,而不必保存指针。由(cons 1 2)制成的Ac cons单元格将有指向数字的指针,但可以直接存储它们(对于其他一些小项目,如字符,也是如此)。