14

(免责声明 - 我知道 Clojure 中 Seqs 的重要性)

在常见的 lisp 中, cons 函数可用于将两个符号组合成一个列表:

(def s 'x)
(def l 'y)
(cons s l)

在 clojure 中-您只能将 cons 放入序列中- cons 尚未扩展为使用两个符号。所以你必须写:

(def s 'x)
(def l 'y)
(cons s '(l))

Clojure 中是否有更高级别的模式来解释 Common LISP 和 Clojure 之间的这种差异?

4

5 回答 5

9

在 Clojure 中,与传统的 Lisps 不同,列表不是主要的数据结构。数据结构可以实现ISeq接口——这是给定数据结构的另一个视图——允许相同的函数访问每个接口中的元素。(列表已经实现了这一点。检查seq?是否有实现ISeq 。Clojure(seq? '(1 2)), (seq? [1 2]))只是行为不同(有充分的理由),因为当cons使用时,一个序列(它实际上是 type clojure.lang.Cons)构造a(seq b)返回。(a是 arg 1 和barg 2)显然,符号不会也不能实现ISeq

Clojure.org/sequences

Rich Hickey 的序列截屏视频/谈话但是,请注意,它rest已经改变了,它以前的行为现在是 in next,并且lazy-cons已经被lazy-seqand取代了cons

clojure.lang.RT

于 2010-07-11T11:41:36.967 回答
6

在 Common Lisp 中,CONS 创建了一个所谓的 CONS 单元,它类似于具有两个插槽的记录:“car”和“cdr”。

您可以将任何东西放入 cons 单元的这两个插槽中。

缺点单元用于构建列表。但是可以使用 cons 单元创建各种数据结构:树、图表、各种类型的专用列表,......

Lisp 的实现经过高度优化以提供非常高效的 cons 单元。

于 2010-07-11T11:41:49.197 回答
3

Lisp 列表只是使用 cons 单元格的一种常见方式(请参阅Rainer 的描述)。Clojure 最好被视为没有 cons 单元格(尽管类似的东西可能隐藏在引擎盖下)。Clojurecons用词不当,实际上应该命名为prepend.

于 2010-07-11T12:37:15.910 回答
3

在 Clojure 中,首选使用二元素向量:[:a :b]. 在底层,这样的小向量被实现为 Java 数组,并且非常简单和快速。

(cons :a '(:b))(或(cons :a (cons :b nil)))的简写是list(list :a :b)

于 2010-07-12T05:42:55.487 回答
2

当你说

> (cons 'a 'b)

在普通的 lisp 中,您不会得到一个列表,而是一个点对: (a . b),而结果

> (cons 'a (cons 'b nil))

是虚线对(a . ( b . nil))

在第一个列表中cdr(),那不是列表,因为它在此处b而不是nil,因此使其成为不正确的列表。正确的列表必须以 . 结尾nil。因此,像和朋友这样的高阶函数mapcar()将不起作用,但我们保存了一个 cons-cell。我猜 Clojure 的设计者删除了这个特性,因为它可能引起混乱。

于 2010-07-11T11:36:41.247 回答