从向量/分块序列中构建的懒序列有时会进行缓慢的第一次/下一次reduce。
观察
`
(def xs (vec (range 3000000)))
(time (reduce max xs)) ;; #1: 130ms, (参考)
(time (reduce max (lazy-cat xs))) ;; #2: 130ms,同样快
(time (reduce max 0 (lazy-cat xs))) ;; #3: 500ms,慢4倍!!
;; 使用concat加倍,它们不会慢2倍,而是慢10倍
(time (reduce max (lazy-cat xs xs))) ;; #4: 1200ms
(time (reduce max 0 (lazy-cat xs xs))) ;; #5: 1200ms
`
对于#3的解释:问题在于 {{seq-reduce}} 在没有 {{init}} 的情况下调用时,将正确地再次调用 {{reduce}} 并采取一个快速的路径。当提供了 {{init}} 时,它不会逃离到一个更快的reduce,而会坚持使用第一个/下一个。
注意:在Clojure中,它们扩展得“适当”(前三个约45ms,最后两个约110ms)。
原因在于Clojure正确地逃离到一个快速路径
https://github.com/clojure/clojure/blob/2b242f943b9a74e753b7ee1b951a8699966ea560/src/clj/clojure/core/protocols.clj#L131-L143
这是一个RFC,因为我不是百分之百确定实现方法。需要小心不要在这里压塌堆栈...
问题
1. Should ChunkedCons实现IReduce? 我想是的。