Transducers are composable components for processing data independently of the context. So they can be used to process collections, streams, channels, etc. without knowledge of their input sources or output sinks.
The Clojure core library was extended in 1.7 so that the sequence functions like map, filter, take, etc. return a transducer when called without a sequence. Because transducers are functions with specific contracts, they can be composed using the normal comp
function.
Transducers allow the lazyness to be controlled as they are consumed. For example into
is eager as would be expected, but sequence
will lazily consume the sequence through the transducer. However, the lazyness guarantee is different. Enough of the source will be consumed to produce an element initially:
(take 0 (sequence (map #(do (prn '-> %) %)) (range 5)))
;; -> 0
;; => ()
Or decide if the list is empty:
(take 0 (sequence (comp (map #(do (prn '-> %) %)) (remove number?)) (range 5)))
;; -> 0
;; -> 1
;; -> 2
;; -> 3
;; -> 4
;; => ()
Which differs from the usual lazy sequence behaviour:
(take 0 (map #(do (prn '-> %) %) (range 5)))
;; => ()