评论由:jdevuyst制作
嗯。我想惰性序列确实会导致许多分配。
好的,我已经重写了我的测试并在更多次数上运行了它。现在我在数组和向式中也进行了测试。
补丁1需要微调。当调用coll-fold时,补丁1只为类型{{object}}指定了一个回退(即调用r/reduce)。我必须为类型{{array}}添加相同的回退。(这很奇怪!)
所以,以下是结果。
对于向量
`
(let [coll (vec (repeat 100 (vec (range 100))))]
(时间 (dotimes [n 3000]
(->> coll
(r/mapcat identity)
(r/map inc)
(r/filter even?)
(r/fold +)))))
`
补丁1: 205872 毫秒
补丁2: 210756 毫秒
对于数组
`
(let [coll (into-array (repeat 100 (into-array (range 100))))]
(时间 (dotimes [n 3000]
(->> coll
(r/mapcat identity)
(r/map inc)
(r/filter even?)
(r/fold +)))))
`
补丁1: 123567 毫秒
补丁2: 119704 毫秒
我进行了几次测试,结果相当一致。补丁1对向量更快,而补丁2对数组更快。
这是有道理的。
在补丁1中,{{reducer}}将直接调用{{-reduce}}。在补丁2中,{{reducer}}首先调用{{r/reduce}},该函数在集合是向量时调用{{-reduce}},如果是数组则调用{{array-reduce}}。因此,在向量的情况下,补丁2包含一个额外的函数调用,但在数组的情况下避免了对原生类型协议方法的调用。
使用宏(或复制粘贴)可以避免额外的函数调用。这值得尝试吗,或者保持代码清洁更重要?
--
我突然意识到补丁2在语义上稍微与Clojure不同,尽管这可能是Clojure的一个错误:[链接](https://groups.google.com/forum/#!searchin/clojure-dev/kv-reduce/clojure-dev/bEqECvbExGo/iW4B2vEUh8sJ)。我将使用宏(或复制粘贴)的建议以避免补丁2中的额外函数调用可能也解决了这个差异。