Clojure - 为什么使用列表而不是向量表现不同?

时间:2013-12-01 16:43:39

标签: clojure

当插入的集合不同时,为什么into的行为会有所不同?例如:

user=> (into [] [1 2 3])
[1 2 3]

到目前为止,这么好。正如我所料。但是:

user=> (into () [1 2 3])
(3 2 1)

为什么这会颠倒争论?我假设它是为了性能,并且项目是按cons顺序插入的?这似乎打破了我的抽象,在两个不同类型的有序集合中,我希望结果能够一致地排序。

2 个答案:

答案 0 :(得分:7)

into一起conjseq

conj在开头添加列表,并在结尾添加向量以提高效率,这样就不会遍历任何一种类型以便添加它。

在谈论Clojure中的Collection抽象时,Programming Clojure很好地解释了这一点:

  

这些函数(conj / seq / count / empty / =)都是多态的   关于正在进行的具体收集类型。说过   换句话说,每个操作都提供与语义一致的语义   每个数据结构实现的约束。

答案 1 :(得分:0)

作为@MarkFisher的answer的补遗:into类似于reduce conj; into的行为差异来自conj的行为差异:

(conj '(:b :c) :a)             ;; '(:a :b :c)      ;; prepend to lists
(conj  [:a :b] :c)             ;; [:a :b :c]       ;; append to vectors

(conj #{:a :b}    :c)          ;; #{:a :b :c}      ;; add to sets
(conj #{:a :b :c} :c)          ;; #{:a :b :c}      ;; nothing if already there

(conj {:a 1 :b 2}      [:c 3]) ;; {:a 1 :b 2 :c 3} ;; add key-value
(conj {:a 1 :b 2 :c 3} [:c 4]) ;; {:a 1 :b 2 :c 4} ;; replace value if present

编辑:我最近使用了conj的多态性。编写一个回文生成器,可以使用相同的函数生成回文的头部和尾部,只需通过喂食矢量或列表即可。