Notes and examples of Transducers and Reducers
- 
Used on collections 
- 
Eager evaluation only. (not lazy) 
- 
The operation(s) and the input are no longer tied together 
     
(r/map zero?)
;=> #<reducers$map$fn__2527 clojure.core.reducers$map$fn__2527@7201f000>
(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)
(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]
- 
Can be used in ClojureScript 
- 
Function C is the reducing function 
- 
Function B calls Function C 
- 
Function A creates Function B 
- 
(A C) -> B 
(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 
     
     (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
(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
(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