## Transducers and Reducers Notes and examples of Transducers and Reducers ### Reducers * Used on collections * Eager evaluation only. (not lazy) * The operation(s) and the input are no longer tied together ```clojure (r/map zero?) ;=> # (let [map-zero? (r/map zero?) inputs [0 1 0 1 0 1]] (reduce conj [] (map-zero? inputs))) ;=> [true false true false true false] ``` * Can be combined into a single function for better performance. (composable) ```clojure (def zero?-and-not-false (comp (r/filter true?) (r/map zero?))) ;=> #'user/zero?-and-not-false (reduce conj [] (zero?-and-not-false [0 1 0 1 0 1])) [true true true] ``` ### Transducers * Can be used in ClojureScript * Function C is the reducing function * Function B calls Function C * Function A creates Function B * (A C) -> B ```clojure (defn a [c] (fn b ([] (c)) ([coll] (c coll)) ([coll input] (c coll input)))) ;=> #'user/a (transduce a + [1 2 3]) ;=> 6 ``` * Doesn't care about the input type * Transducers seem to be faster than reducers ```clojure (dotimes [n 5] (time (r/reduce + 0 [1 2 3]))) "Elapsed time: 0.23142 msecs" "Elapsed time: 0.047252 msecs" "Elapsed time: 0.043944 msecs" "Elapsed time: 0.062372 msecs" "Elapsed time: 0.05938 msecs" ;=> nil (dotimes [n 5] (time (transduce a + 0 [1 2 3]))) "Elapsed time: 0.1257 msecs" "Elapsed time: 0.026548 msecs" "Elapsed time: 0.018166 msecs" "Elapsed time: 0.031276 msecs" "Elapsed time: 0.024773 msecs" ;=> nil ``` * Collection fns of previous Clojure versions are now optionally Transducers ```clojure (let [*2 #(* % 2) *4 #(* % 4)] (def weird-composition (comp (filter even?) (map *2) (map *4)))) ;=> #'user/weird-composition (into [] weird-composition [1 2 3 4]) ;=> [16 32] ``` * For lazy transformations you must use ```sequence``` ```clojure (def star-wrap (map #(str "*" % "*"))) ;=> #'user/star-wrap (into [] star-wrap [1 2 3]) ;=> ["*1*" "*2*" "*3*"] (sequence star-wrap [1 2 3]) ;=> ("*1*" "*2*" "*3*") (type (into [] star-wrap [1 2 3])) ;=> clojure.lang.PersistentVector (type (sequence star-wrap [1 2 3])) ;=> clojure.lang.LazyTransformer ```