我听说clojure没有大多数lisp语言的cons细胞.
这是否意味着clojure列表不以空列表结尾?
任何人都能解释这究竟意味着什么?
Lisp为它提供了原始的cons数据结构和符号.
参见John McCarthy,符号表达式的递归函数及其机器计算,第一部分,1960年,第3章,符号表达式的递归函数.
该章介绍:
符号表达式由原子和符号表达式组成,使用点符号表示: ( a . b )
用于缩写某些符号表达式的列表表示法 (a b c)
nil
用于终止列表的原子符号
原始功能car
,cdr
,cons
,eq
和atom
其他几个功能:ff
,subst
,equal
,null
,cadr
,caddr
,null
,append
,among
,pair
,assoc
,sublis
,apply
,eval
,...
在早期的Lisp中,添加了改变cons单元的函数:( rplaca
意思是替换汽车)和rplacd
(意味着替换cdr).参见John McCarthy等人的LISP 1.5程序员手册.从1962年.这些函数允许我们编写破坏性函数,并允许我们创建循环的基于cons的数据结构,如循环列表.
Common Lisp
通常,Lisp方言实现了大部分.Common Lisp也不例外,它的功能在Common Lisp标准中描述:Conses.使用上述功能的示例:
; pair two lists into a list of cons cells ; the function pair is called pairlis in Common Lisp CL-USER 17 > (pairlis '(john mary eva) `(34 29 40)) ((EVA . 40) (MARY . 29) (JOHN . 34)) ; find a cons cell in a list of cons cells, based on the content of the car of those cons cells CL-USER 18 > (assoc 'eva (pairlis '(john mary eva) `(34 29 40))) (EVA . 40) ; create a tree out of cons cells and atoms CL-USER 19 > (cons (cons 10 20) (cons 30 40)) ((10 . 20) 30 . 40) ; a cons cell is not an atom CL-USER 20 > (atom (cons 1 2)) NIL ; a cons cell is not nil CL-USER 21 > (null (cons 1 2)) NIL ; substitute an item with a new one in a tree CL-USER 22 > (subst 30 ; new 'bar ; old '((10 . 20) . (bar . 40))) ; tree ((10 . 20) 30 . 40) ; also written as ((10 . 20) . (30 . 40)) ; substitute several items in a tree, using an assoc list ; to describe the substitutions CL-USER 23 > (sublis '((a . 10) (d . 40)) ; substitutions '((a . b) . (c . d))) ; tree ((10 . B) C . 40)
列表是符号表达式的特例.它们通常没有点写:
CL-USER 24 > '(a . (b . nil)) (A B)
Common Lisp还支持变异操作rplaca
和rplacd
Lisp 1.5:
CL-USER 25 > (let ((c (cons 0 1))) ; create a cons (print c) ; print it (print (rplaca c 'foo)) ; replace the car (print (rplacd c 'bar)) ; replace the cdr (print (eq c (rplaca c 'baz))) ; identical ? (values)) (0 . 1) ; the cons cell (FOO . 1) ; car replaced (FOO . BAR) ; cdr replaced T ; still the same object
Emacs Lisp
Emacs Lisp还实现了上述功能:
ELISP> (sublis '((a . 10) (d . 40)) '((a . b) . (c . d))) ((10 . b) c . 40)
Clojure的
Clojure不支持John McCarthy所描述的这些符号表达.它没有缺陷单元,没有点符号,也没有提供上述接口.例如,原子 意味着Clojure中完全不同的东西.cons
没有创建一个利弊细胞.列表不是由cons细胞组成的.
在Clojure中,一个点只是另一个符号:
user=> (count '(1 . 2)) 3
有一个原始函数来构造列表:
user=> (list 1 2 3) (1 2 3)
结果应该是一个列表:
user=> (list? (list 1 2 3)) true
有一个函数叫cons
:
user=> (cons 0 (list 1 2 3)) (0 1 2 3)
不知何故,这不是一个列表:
user=> (list? (cons 0 (list 1 2 3))) false
基本上Clojure使用不同的数据结构( - > 序列,逻辑列表)和自己的命名和语义.即使名称与Lisp名称相似,也不要指望它们做同样的事情.
方案
编程语言Scheme还提供与上述类似的cons单元.它缺少一些功能,但可以很容易地实现.例如,sublis
可以在Scheme中实现(参见initdr.scm):
(define (sublis alist tree) (if (pair? tree) (cons (sublis alist (car tree)) (sublis alist (cdr tree))) (if (assv tree alist) (cdr (assv tree alist)) tree)))
Clojure确实有一个缺点:clojure.lang.Cons
.
它用于cons
调用的结果
......别无其他:既不是列表,也不是矢量,也不是任何类型的懒惰序列.
它也不能用于一般的物体对:尾部/ rest
/ cdr
是一个序列,而不是一个序列Object
.
如果你cons
在列表,矢量或懒惰序列上的东西,你会得到一个Cons
.
但是,正如其他答案所说的那样,没有任何函数可以处理Cons
.它们都是按顺序处理的.
另一个用途:conj
进入一个不确定的序列(矢量列表,既不设置也不映射......)产生一个Cons
.
根据clojure.org的这个页面:
缺点,首先和休息操纵序列抽象,而不是具体的利弊细胞
Clojure列表不以空列表结尾,它们不是传统的cons单元格.它们是实现排序的数据结构. 这个关于抽象编程的页面解释了Clojure对"seqable"结构的方法,包括列表:
通常,对抽象的编程可以让您在不同的数据结构上使用函数库,而不管这些数据结构的实现方式.
所以Clojure的列表是像他们实现利弊细胞cons
,first
以及 rest
但这仅仅意味着它们共享一个通用的接口.它们的底层实现有所不同,但它们都是"可选的".