A transducer composition combines transformations into one reusable transformation. In Clojure, collection-free calls such as (filter odd?) and (map inc) produce transducers; comp joins them. Applied through transduce, the chain processes a collection in a single pass without producing an intermediate result for each step. section 7.0 section 7.2
Compose, then reduce
(transduce (comp (filter odd?) (map inc)) + (range 10)) ;; 30 The chain keeps odd numbers, increments them, then sums them. Compare (reduce + (map inc (filter odd? (range 10)))), which also returns 30. In a transducer chain, write the transformations in the order each input should encounter them. section 7.2.1 section 2.2.2
Choose how to run the composed transformation:
- Use transduce with a reducing function, an optional initial accumulator, and a collection to produce a final reduction result. section 7.2.1
- Use sequence or eduction to obtain transformed elements, or into to copy them into another collection. section 7.2
(require '[clojure.string :refer [starts-with? split-lines]])
(defn alaska? [postcode]
(starts-with? postcode "99"))
(defn unique-postcodes [mailing]
(sequence (comp
(map :label)
(map split-lines)
(map last)
(remove alaska?) ; #1
(distinct))
mailing))
(unique-postcodes mailing)
;; ("43793" "75395")
A mailing-list pipeline extracts postcodes, removes those starting with 99, and eliminates duplicates. Its sequence call shows how a composed chain can remain separate from the input collection. section 2.2.2
A custom transducer accepts a reducing function and returns a transformed reducing function with step and completion arities. For ordinary composition, collection-free core functions avoid that implementation work. Transducers emphasize reuse; unlike reducers, parallel use is reliable only for stateless transducers. section 7.2.1 section 7.0
