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在编程语言及其实现的研究中,广义的用法意味着"构建某种类型或其他类型的记录以保持一些价值"在目前无处不在; 这就是提到"避免消费"时的含义.
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中的并发章节.