

A reducer is the combination of a reducible collection (a collection that knows how to reduce itself) with a reducing function (the "recipe" for what needs to be done during the reduction). The standard sequence operations are replaced with new versions that do not perform the operation but merely transform the reducing function. Execution of the operations is deferred until the final reduction is performed. This removes the intermediate results and lazy evaluation seen with sequences.

  2. Applying reduce to each partition
  3. Recursively combining each partition using Java's fork/join framework.


reduce and fold


(r/reduce f coll)
(r/reduce f init coll)

The reducers version differs in that:
  • Map colls are reduced with reduce-kv


(r/fold reducef coll)
(r/fold combinef reducef coll)
(r/fold n combinef reducef coll)



Using reducers

Use fold to sum with +:
(require '[clojure.core.reducers :as r])
(r/fold + (r/filter even? (r/map inc [1 1 1 2])))
;=> 6
Use into to produce a final collection:
(into [] (r/filter even? (r/map inc (range 100000))))
Or r/foldcat:
(r/foldcat (r/filter even? (r/map inc (range 100000))))
Specify a reduce function and a combine function with fold:
(defn count-words
  ([] {})
  ([freqs word]
    (assoc freqs word (inc (get freqs word 0)))))
(defn merge-counts
  ([] {})
  ([& m] (apply merge-with + m)))
(defn word-frequency [text]
  (r/fold merge-counts count-words (clojure.string/split text #"\s+")))

When to use

Use the reducer form of these operations when:
  • Source data can be generated and held in memory
  • Work to be performed is computation (not I/O or blocking)
  • Number of data items or work to be done is "large"
Logo & site design by Tom Hickey.