在使用reducers时,我偶尔会使用 foldcat 通过reducer链“实现”转换后的集合。对于后续的代码,最好使用一个完全实现的标准的 clojure 集合,如 vec
。当为了性能原因将核心集合代码更新为使用reducers时,这通常是这样的。
以下代码可以正常工作:
(->> (repeat 2 3) (vec) (r/map inc) (r/foldcat) (vec))
=> [4 4]
然而,当输入足够大时,这会触发并行行为,将返回类型从 Array 更改为 Cat,导致最后一个 vec
扛不住。
(->> (repeat 513 3) (vec) (r/map inc) (r/foldcat) (vec))
Execution error at user/eval19976 (form-init6687476487684153971.clj:1).
Unable to convert: class clojure.core.reducers.Cat to Object[]
我认为“正确”的方式是使用 (into [])
而不是在最后一个位置使用 vec
,这样效果很好。
话虽如此,这种行为相当令人惊讶,因为 seq
和 into
在 Array
和 Cat
上都能很好地工作。这也非常危险,因为这样的代码可以在生产环境中安静地运行,直到输入数据超过某个阈值。为什么 seq
能在 Cat
上工作,而 vec
不能,有现实的原因吗?