A slightly modified version of reduce
was introduced with reducers, clojure.core.reducers/reduce
(short r/reduce
):
(defn reduce
([f coll]
(reduce f (f) coll))
([f init coll]
(if (instance? java.util.Map coll)
(clojure.core.protocols/kv-reduce coll f init)
(clojure.core.protocols/coll-reduce coll f init))))
r/reduce
differs from its core sibling only in that it uses (f)
as the initial value when none is provided, and it delegates to core reduce-kv
for maps.
I don’t understand what use such an odd special-purpose reduce
might be and why it was worth including in the reducers library.
Curiously, r/reduce
is not mentioned in the two introductory blog posts as far as I can tell (first, second). The official documentation notes
In general most users will not call r/reduce directly and instead should prefer r/fold (...) However, it may be useful to execute an eager reduce with fewer intermediate results.
I’m unsure what that last sentence hints at.
What situations can r/reduce
handle that the core reduces cannot? When would I reach for r/reduce
with conviction?
Two possible reasons:
It has different – better! – semantics than clojure.core/reduce
in the initless sequential case. During his 2014 Conj presentation Rich Hickey asked "who knows what the semantics of reduce
are when you call it with a collection and no initial value?" – follow this link for the exact spot in the presentation – and then described the said semantics as "a ridiculous, complex rule" and "one of the worst things [he] ever copied from Common Lisp" – cf. Common Lisp's reduce
contract. The presentation was about transducers and the context of the remark was a discussion of transduce
, which has a superior, simpler contract; r/reduce
does as well.
Even without considering the above, it's sort of nice to have a version of reduce
with a contract very close to that of fold
. That enables simple "try one, try the other" benchmarking with the same arguments, as well as simply changing one's mind.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With