Clojure:cons(seq)和conj(list) [英] Clojure: cons(seq) vs. conj(list)

查看:114
本文介绍了Clojure:cons(seq)和conj(list)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道 cons 返回一个seq, conj 返回一个集合。我也知道 conj 将项目添加到集合的最佳末尾, cons 总是添加项目到前面。此示例说明了这两点:

  user => (conj [1 2 3] 4)//返回一个集合
[1 2 3 4]
user => (cons 4 [1 2 3])//返回一个seq
(4 1 2 3)

对于向量,地图和集合,这些差异对我有意义。但是,对于列表,它们看起来是相同的。

  user => (conj(list 3 2 1)4)//返回一个列表
(4 3 2 1)
user => (cons 4(list 3 2 1))//返回一个seq
(4 3 2 1)


$ b b

有任何使用列表的示例,其中 conj cons 展示不同的行为, ?换句话说,有一个例子,列表和seq不能等价使用?

解决方案

$ c> conj 接受任何数量的参数插入到集合中, cons 只有一个:

 (conj(1 2 3)4 5 6)
; => (6 5 4 1 2 3)

(cons 4 5 6'(1 2 3))
; => IllegalArgumentException由于错误的arity

另一个区别是返回值的类:

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

(class(cons 4'(1 2 3))
; => clojure.lang.Cons

请注意,这些不是真正可以互换的;特别是 clojure.lang.Cons code> clojure.lang.Counted ,所以一个 count 它不再是一个常量时间操作减少到1 + 3 - 1来自第一个元素的线性遍历,3来自(next(cons 4'(1 2 3)) code> PersistentList ,因此 Counted )。



名称是,我相信, cons 意味着cons(truct a seq) 1 ,而 conj 意味着将一个项目转换到一个集合上。由 cons 构造的 seq 元素作为其第一个参数传递,并且具有 next / rest $ c> seq 到第二个参数;如上所示,整个事情是类 clojure.lang.Cons 。相反, conj 总是返回一个与传递给它的集合大致相同类型的集合。 (大致上,因为 PersistentArrayMap 会在它超过9个条目时就变成 PersistentHashMap 。 p>




1 传统上,在Lisp世界中, cons cons(tructs a pair),因此Clojure从它的 cons 函数构造一个没有传统 cdr 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)

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?

解决方案

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

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).

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 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:cons(seq)和conj(list)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆