liveBook · Manning

Folder

As explained in Clojure: The Essential Reference

A Clojure folder is a collection-enhancing function that supplies custom reducing and folding implementations through a transforming function.

A Clojure folder enhances a collection with custom reducing and folding behavior. It receives a collection and an xf function; xf receives the original reducing function and returns a replacement two-argument reducer. section 7.1.2

Use folder when a transformation must participate in r/fold as well as ordinary reduction. It intercepts reducef behavior, but not combinef, so the reducer must remain compatible with the fold’s partitioning and combination strategy. section 7.1.2

Filtering values inside a fold

A transforming function can pass only keys divisible by 10 to the downstream reducer: (r/folder (zipmap (range 100) (range 100)) (fn [rf] (fn [m k v] (if (zero? (mod k 10)) (rf m k v) m)))). Folding this collection with a map-combining monoid produces entries such as {0 3, 10 13, 20 23, ..., 90 93}. section 7.1.2

Standard reducers such as map, mapcat, filter, remove, flatten, and cat are foldable. take-while, take, and drop are not inherently foldable; custom folder implementations can address stateful behavior when parallel folding requires it. section 7.1.2

Listing 7.2. → Transforming Functions, Reducing Functions, Collection Reduce, Folding
(reducer [coll xf])
(folder [coll xf])

Compare the reducer and folder signatures before choosing collection-level reduction or folding enhancement. section 7.1.2

(require '[clojure.core.reducers :as r])    ; #1

(defn divisible-by-10 [current-reducing-fn] ; #2
  (fn [acc el]
    (if (zero? (mod el 10))
      (current-reducing-fn acc el)
      acc)))

(into []                                    ; #3
  (r/reducer
    (range 100)
    divisible-by-10))
;; [0 10 20 30 40 50 60 70 80 90]

(r/fold                                     ; #4
  (r/monoid merge (constantly {}))
  (fn [m k v] (assoc m k (+ 3 v)))
  (r/folder
    (zipmap (range 100) (range 100))
    (fn [rf] (fn [m k v] (if (zero? (mod k 10)) (rf m k v) m)))))
;; {0 3, 70 73, 20 23, 60 63, 50 53, 40 43, 90 93, 30 33, 10 13, 80 83}

Run a compact folder example that filters values during r/fold and combines the retained results. section 7.1.2

How Clojure: The Essential Reference covers it

How deep it goes
Defines the xf contract and fold boundary, then demonstrates custom reducers and stateful parallel-fold concerns.
Examples
Uses divisibility filtering, deduplication, reducer pipelines, and stateful dropping across ordinary and parallel folds.
What it assumes
Assumes familiarity with collections, reducing functions, reducers, and fold while defining the folder contract explicitly.
What you can do after
Build it from scratch by wrapping a reducing function and applying the wrapper through r/fold or ordinary reduction.
How it connects
Connects reducing functions, reducers, transducers, fold, monoids, combine functions, and parallel reduction.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Clojure: The Essential Reference. The section links point to the parts of the book it draws on.