I know a lot of people find them confusing.
https://web.archive.org/web/20161219045343/https://clojure.o...
Demo One: Computation and Output format pulled apart
(def natural-nums (rest (range)))
(def fizz-buzz-xform
(comp (map basic-buzz)
(take 100))) ;; early termination
(transduce fizz-buzz-xform ;; calculate each step
conj ;; and use this output method
[] ;; to pour output into this data structure
natural-nums)
(transduce fizz-buzz-xform ;; calculate each step
str ;; and use this output method
"" ;; to catenate output into this string
natural-nums) ;; given this input
(defn suffix-comma [s] (str s ","))
(transduce (comp fizz-buzz-xform
(map suffix-comma)) ;; calculate each step
str ;; and use this output method
"" ;; to catenate output into this string
natural-nums) ;; given this input
Demos two and three for your further entertainment are here: https://www.evalapply.org/posts/n-ways-to-fizzbuzz-in-clojur...(edit: fix formatting, and kill dangling paren)
While the mechanics of transducers are interesting the bottom line is they allow you to fuse functions and basic conditional logic together in such a way that you transform a collection exactly once instead of n times, meaning new allocation happens only once. Once you start using them you begin to see intermediate collections everywhere.
Of course, in any language you can theoretically do everything in one hyperoptimized loop; transducers get you this loop without much of a compromise on keeping your program broken into simple, composable parts where intent is very clear. In fact your code ends up looking nearly identical (especially once you learn about eductions… cough).
The real thing to learn is how to express things in terms of reduce. Once you've understood that, just take a look at e.g. the map and filter transducers and it should be pretty obvious. But it doesn't work until you've grasped the fundamentals.
Note: I’m not the author of Injest, just a satisfied programmer.
mannycalavera42•1h ago