Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of clojure.core.reducers/reduce?

Tags:

clojure

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?

like image 970
glts Avatar asked Oct 18 '22 13:10

glts


1 Answers

Two possible reasons:

  1. 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.

  2. 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.

like image 196
Michał Marczyk Avatar answered Nov 02 '22 22:11

Michał Marczyk