Skip to content

Instantly share code, notes, and snippets.

@paultopia
Last active October 17, 2016 04:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paultopia/f374a964038a91e4afdb52c9376d3a33 to your computer and use it in GitHub Desktop.
Save paultopia/f374a964038a91e4afdb52c9376d3a33 to your computer and use it in GitHub Desktop.
clojure[script] transducers: basic use
;; attempted translation of the basic parts of the clojure documentation page on transducers http://clojure.org/reference/transducers
;; into more comprehensible terms that don't require you to be as smart as Rich Hickey to understand.
;; transducers are a way to compose sequence functions with less than their normal arity into a combined transformation
;; which then gets applied more efficiently than just nesting calls to the transformation, using ->, etc.
;; In the below, xf is a transducer. The composition goes left to right, hence tests for oddness before testing for less-than-5ness
(def xf
(comp
(filter odd?)
(filter #(> 5 %))))
;; to just apply the composed transformation to a collection, the easiest thing is to use the `into` idiom
(def example [1 2 3 4 5 6 7 8 9 10])
(into [] xf example)
;; [1 3]
;; `transduce` is just like normal `reduce` but with the xf composed with the reducing function first. The docs are a little obscure
;; on what that means ("with the transducer xform applied to the reducing function f"---huh?) but it seems to mean composition in
;; that sense.
(transduce xf + example)
;; 4
(transduce xf conj [] example)
;; [1 3]
;; I actually find this last one a bit magical. The docs say:
;; "f supplies the knowledge of how to accumulate the result, which occurs in the (potentially stateful) context of the reduce."
;; and what that seems to mean is "it somehow manages to act as if you applied the transducer to the whole collection before reducing."
;; `eduction` seems to basically just mean "create a lazy sequence from applying the transducer to the collection"
(take 2 (eduction xf example))
;; (1 3)
;; for future reference, here's the list of the built-in higher-order sequence functions that make transducers with one less arity,
;; straight from the docs:
;; map cat mapcat filter remove take take-while take-nth drop drop-while replace partition-by partition-all keep keep-indexed
;; map-indexed distinct interpose dedupe random-sample
;; Christophe Grand has also written tranducerific support for more core functions at https://github.com/cgrand/xforms
;; right now they seem a little hard to understand (especially x/reduce!!) but reading the code is interesting...
;; this is a nice SO: http://stackoverflow.com/questions/26317325/can-someone-explain-clojure-transducers-to-me-in-simple-terms
@timgilbert
Copy link

Typo on line 2: "comprensible" -> "comprehensible"

@paultopia
Copy link
Author

thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment