象嘉道*_*象嘉道 12 lisp scheme clojure common-lisp cons
我听说clojure没有大多数lisp语言的cons细胞.
这是否意味着clojure列表不以空列表结尾?
任何人都能解释这究竟意味着什么?
Rai*_*wig 24
Lisp为它提供了原始的cons数据结构和符号.
参见John McCarthy,符号表达式的递归函数及其机器计算,第一部分,1960年,第3章,符号表达式的递归函数.
该章介绍:
( a . b )(a b c)nil用于终止列表的原子符号car,cdr,cons,eq和atomff,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)
Run Code Online (Sandbox Code Playgroud)
列表是符号表达式的特例.它们通常没有点写:
CL-USER 24 > '(a . (b . nil))
(A B)
Run Code Online (Sandbox Code Playgroud)
Common Lisp还支持变异操作rplaca和rplacdLisp 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
Run Code Online (Sandbox Code Playgroud)
Emacs Lisp
Emacs Lisp还实现了上述功能:
ELISP> (sublis '((a . 10) (d . 40))
'((a . b) . (c . d)))
((10 . b) c . 40)
Run Code Online (Sandbox Code Playgroud)
Clojure的
Clojure不支持John McCarthy所描述的这些符号表达.它没有缺陷单元,没有点符号,也没有提供上述接口.例如,原子 意味着Clojure中完全不同的东西.cons没有创建一个利弊细胞.列表不是由cons细胞组成的.
在Clojure中,一个点只是另一个符号:
user=> (count '(1 . 2))
3
Run Code Online (Sandbox Code Playgroud)
有一个原始函数来构造列表:
user=> (list 1 2 3)
(1 2 3)
Run Code Online (Sandbox Code Playgroud)
结果应该是一个列表:
user=> (list? (list 1 2 3))
true
Run Code Online (Sandbox Code Playgroud)
有一个函数叫cons:
user=> (cons 0 (list 1 2 3))
(0 1 2 3)
Run Code Online (Sandbox Code Playgroud)
不知何故,这不是一个列表:
user=> (list? (cons 0 (list 1 2 3)))
false
Run Code Online (Sandbox Code Playgroud)
基本上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)))
Run Code Online (Sandbox Code Playgroud)
clojure.lang.Cons.cons调用的结果rest/ cdr
是一个序列,而不是一个序列Object.cons在列表,矢量或懒惰序列上的东西,你会得到一个Cons.Cons.它们都是按顺序处理的.另一个用途:conj进入一个不确定的序列(矢量列表,既不设置也不映射......)产生一个Cons.
缺点,首先和休息操纵序列抽象,而不是具体的利弊细胞
Clojure列表不以空列表结尾,它们不是传统的cons单元格.它们是实现排序的数据结构. 这个关于抽象编程的页面解释了Clojure对"seqable"结构的方法,包括列表:
通常,对抽象的编程可以让您在不同的数据结构上使用函数库,而不管这些数据结构的实现方式.
所以Clojure的列表是像他们实现利弊细胞cons,first以及 rest但这仅仅意味着它们共享一个通用的接口.它们的底层实现有所不同,但它们都是"可选的".