Clojure:缺点(seq)与缺点(清单) [英] Clojure: cons (seq) vs. conj (list)
问题描述
我知道 cons
返回一个序列,而 conj
返回一个集合。我也知道 conj
将项目添加到集合的最佳末端,而 cons
总是添加该项目在最前面。此示例说明了这两点:
I know that cons
returns a seq and conj
returns a collection. I also know that conj
"adds" the item to the optimal end of the collection, and cons
always "adds" the item to the front. This example illustrates both of these points:
user=> (conj [1 2 3] 4) ; returns a collection
[1 2 3 4]
user=> (cons 4 [1 2 3]) ; returns a seq
(4 1 2 3)
对于矢量,地图并设置这些差异对我来说很有意义。但是,对于列表而言,它们似乎是相同的。
For vectors, maps, and sets these differences make sense to me. However, for lists they seem identical.
user=> (conj (list 3 2 1) 4) ; returns a list
(4 3 2 1)
user=> (cons 4 (list 3 2 1)) ; returns a seq
(4 3 2 1)
是否有使用列表的示例,其中 conj
与 cons
表现出不同的行为,还是它们真正可互换?措辞不同,是否有一个示例,其中列表和seq不能等效使用?
Are there any examples using lists where conj
vs. cons
exhibit different behaviors, or are they truly interchangeable? Phrased differently, is there an example where a list and a seq cannot be used equivalently?
推荐答案
一个区别是 conj
接受任意数量的参数插入集合,而 cons
只接受一个参数:
One difference is that conj
accepts any number of arguments to insert into a collection, while cons
takes just one:
(conj '(1 2 3) 4 5 6)
; => (6 5 4 1 2 3)
(cons 4 5 6 '(1 2 3))
; => IllegalArgumentException due to wrong arity
另一个区别是返回值的类别:
Another difference is in the class of the return value:
(class (conj '(1 2 3) 4))
; => clojure.lang.PersistentList
(class (cons 4 '(1 2 3))
; => clojure.lang.Cons
请注意,它们并不是真正可以互换的;特别是 clojure.lang.Cons
不能实现 clojure.lang.Counted
,因此对其上的 count
不再是固定时间的操作(在这种情况下,减少到1 + 3-1来自第一个元素的线性遍历,3来自(next(cons 4'(1 2 3))
是 PersistentList
,因此已计数
)。
Note that these are not really interchangeable; in particular, clojure.lang.Cons
does not implement clojure.lang.Counted
, so a count
on it is no longer a constant time operation (in this case it would probably reduce to 1 + 3 -- the 1 comes from linear traversal over the first element, the 3 comes from (next (cons 4 '(1 2 3))
being a PersistentList
and thus Counted
).
我相信,名字是 cons
的意思是构造(构造一个序列) 1 ,而 conj
的意思是conj(将一个项目放入集合中)。 cons
正在构建的 seq
以元素作为第一个参数传递,并具有 next
/ rest
部分作为应用<$ c的结果$ c>序列到第二个参数;如上所示,整个内容属于 clojure.lang.Cons
类。相反, conj
总是返回与传递给它的集合大致相同类型的集合。 (大致来说,因为 PersistentArrayMap
一旦增长到超过9个条目,就会被转换为 PersistentHashMap
。)
The intention behind the names is, I believe, that cons
means to cons(truct a seq)1, whereas conj
means to conj(oin an item onto a collection). The seq
being constructed by cons
starts with the element passed as its first argument and has as its next
/ rest
part the thing resulting from the application of seq
to the second argument; as displayed above, the whole thing is of class clojure.lang.Cons
. In contrast, conj
always returns a collection of roughly the same type as the collection passed to it. (Roughly, because a PersistentArrayMap
will be turned into a PersistentHashMap
as soon as it grows beyond 9 entries.)
1 传统上,在Lisp世界中, cons
cons(构成一对),因此Clojure偏离了Lisp的传统,因为它的 cons
函数构造了一个没有传统的 cdr
。在编程语言及其实现的研究中, cons
的普遍用法是指构造某种类型的记录以将多个值组合在一起。这就是提到避免打扰的意思。
1 Traditionally, in the Lisp world, cons
cons(tructs a pair), so Clojure departs from the Lisp tradition in having its cons
function construct a seq which doesn't have a traditional cdr
. The generalised usage of cons
to mean "construct a record of some type or other to hold a number of values together" is currently ubiquitous in the study of programming languages and their implementation; that's what's meant when "avoiding consing" is mentioned.
这篇关于Clojure:缺点(seq)与缺点(清单)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!