Clojure transducers.


;; transduce acts like reduce, but the order of evaluation is different:
;; it visits each element once, applying the transformation function
;; and the combining function.
;; (map inc) is a transformation function that will be applied to
;; a collection before reducing
(transduce (map inc) + '(0 1 2 3 4))

;; The result is the same as:
(reduce + (map inc '(0 1 2 3 4)))

;; but the order of evaluation is the same as (only one traversal):
;; note that we need the "seed" here, otherwise the first element
;; isn't incremented
(reduce #(+ %1 (inc %2)) 0 '(0 1 2 3 4))

;; transduce can also take a "seed":
(transduce (map inc) * 1 '(0 1 2 3 4))

;; this is equivalent to:
(reduce #(* %1 (inc %2)) 1 '(0 1 2 3 4))

;; using filter in a transducer:
(transduce (filter even?) conj '(0 1 2 3 4))

;; the same as:
(reduce #(if (even? %2) (conj %1 %2) %1) [] '(0 1 2 3 4))

;; note that using '() as the seed reverses the order:
(reduce #(if (even? %2) (conj %1 %2) %1) '() '(0 1 2 3 4))

;; 'into' can also be used as a transducing function:
(into [] (filter even?) '(0 1 2 3 4))

;; note that 'map' and 'filter' resolve the ambiguity of how the transform should be used:
(transduce (filter even?) conj '(0 1 2 3 4))
(transduce (map even?) conj '(0 1 2 3 4))

;; one can compose transforming functions (note the order: filter is applied first!):
(transduce (comp (filter even?) (map inc)) conj '(1 2 3))

;; it is common to save transforming functions in a variable:
(def xf (comp (map :a) (filter #(< % 2))))

(transduce xf conj '({:a 1} {:a -4 :b 2} {:a 5}))

;; there are other functions that can act as transforming functions:
;; take, drop, replace, keep, partition,....
;; There are also other functions, besides tarnsduce and into, that can act as
;; sequence, iteration.

CSci 4651 course web site.

The views and opinions expressed in this page are strictly those of the page author. The contents of this page have not been reviewed or approved by the University of Minnesota.