Clojure:cons(seq)vs. conj(list)

dby*_*rne 96 collections clojure sequence

我知道cons返回一个seq并conj返回一个集合.我也知道conj将项目"添加"到集合的最佳末端,并cons始终将项目"添加"到前面.这个例子说明了这两点:

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)
Run Code Online (Sandbox Code Playgroud)

对于矢量,地图和集合,这些差异对我来说很有意义.但是,对于列表,它们似乎相同.

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)
Run Code Online (Sandbox Code Playgroud)

是否有任何使用列表的示例,其中conjvs cons表现出不同的行为,或者它们是否真的可以互换?换句话说,有一个例子,列表和seq不能等效使用吗?

Mic*_*zyk 146

一个区别是conj接受任意数量的参数插入到集合中,而cons只需要一个:

(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
Run Code Online (Sandbox Code Playgroud)

另一个区别在于返回值的类:

(class (conj '(1 2 3) 4))
; => clojure.lang.PersistentList

(class (cons 4 '(1 2 3))
; => clojure.lang.Cons
Run Code Online (Sandbox Code Playgroud)

请注意,这些并不是真正可以互换的; 特别是,clojure.lang.Cons没有实现clojure.lang.Counted,因此count它不再是一个恒定的时间操作(在这种情况下,它可能会减少到1 + 3 - 1来自第一个元素的线性遍历,3来自(next (cons 4 '(1 2 3))a PersistentList和因此Counted).

我认为,这些名称背后的意图是cons指利弊(truct a seq)1,而conj意味着联合(将物品加入集合).在seq由构建cons与作为第一个参数传递的元素开始,并具有作为其next/ rest部分从所述应用所产生的事seq的第二个参数; 如上所示,整件事都是上课的clojure.lang.Cons.相反,conj始终返回与传递给它的集合大致相同类型的集合.(粗略地说,因为一旦超过9个条目,它就会PersistentArrayMap变成一个PersistentHashMap.)


1传统上,在Lisp世界中,conscons(结合一对),所以Clojure脱离了Lisp传统,使其cons功能构造了一个没有传统的seq cdr.cons在编程语言及其实现的研究中,广义的用法意味着"构建某种类型或其他类型的记录以保持一些价值"在目前无处不在; 这就是提到"避免消费"时的含义.

  • 写得真棒!我不知道有一个 Cons 类型。做得好! (3认同)
  • 顺便提一下,作为一个特例,`(cons foo nil)`返回单例'PersistentList`(同样也用于`conj`). (2认同)
  • 另一个精彩的解释。你真是一个 clojure 绝地! (2认同)
  • 根据我的经验,当性能很重要时,将列表视为列表而不是序列非常重要。 (2认同)

Dan*_*sky 10

我的理解是你所说的是真的:列表中的conj等同于列表中的缺点.

您可以将conj视为"插入某处"操作,并将其视为"插入头部"操作.在列表中,插入头部是最合乎逻辑的,因此在这种情况下,结合和缺点是等效的.


小智 8

另一个区别是因为conj将序列作为第一个参数,它alter在更新ref某个序列时很好地起作用:

(dosync (alter a-sequence-ref conj an-item))
Run Code Online (Sandbox Code Playgroud)

这基本上(conj a-sequence-ref an-item)以线程安全的方式进行.这不适用cons.有关详细信息,请参阅Stu Halloway 编程Clojure中的并发章节.