Skip to content

Instantly share code, notes, and snippets.

@madstap
Created October 6, 2017 11:37
Show Gist options
  • Save madstap/4db1c842065d79efb383955d429ef8e8 to your computer and use it in GitHub Desktop.
Save madstap/4db1c842065d79efb383955d429ef8e8 to your computer and use it in GitHub Desktop.
;; Reducing function:
;; A function that takes an accumulator and an item and returns a new accumulator.
;; Like the function you would pass to reduce.
;; Transducer:
;; A function that takes a reducing function and
;; returns a new reducing function.
;; Slightly simplified, this is the meat of map with arity one.
(fn [f]
(fn [rf]
(fn [acc x]
(rf acc (f x)))))
;; So when you call it with vec, it returns something like this. (A transducer)
(map vec)
;;=>
(fn [rf]
(fn [acc x]
(rf acc (vec x)))) ; f is now vec
;; Then, when you call _that_ with conj, which is a reducing function,
;; it returns a new reducing function.
((map vec) conj)
;=>
(fn [acc x]
(conj acc (vec x))) ; rf is now conj
;; The nice thing is that since the result is a reducing function,
;; you can pass _that_ to another transducer, and pass that result to
;; yet another transducer. They compose.
;; These are equivalent:
(((map vec) conj) {} '(1 2))
((fn [acc x]
(conj acc (vec x))) {} '(1 2))
;; As are these:
(reduce ((map vec) conj) {} '((1 2) (3 4) (5 6)))
(reduce (fn [acc x]
(conj acc (vec x))) {} '((1 2) (3 4) (5 6)))
@rockBreaker
Copy link

Thanks! This made it clear 👍

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