Skip to content

Instantly share code, notes, and snippets.

@skatenerd
Created November 13, 2015 18:03
Show Gist options
  • Save skatenerd/91a6566713c856a13543 to your computer and use it in GitHub Desktop.
Save skatenerd/91a6566713c856a13543 to your computer and use it in GitHub Desktop.
interactively understanding transducers
user=> (def increment-a-list (map inc))
#'user/increment-a-list
;I have partially-applied "map". It didn't blow up with an arity error. Success!
;Let's use it
user=> (increment-a-list [1,2,3])
#object[clojure.core$map$fn__4549$fn__4550 0x7ebed7f2 "clojure.core$map$fn__4549$fn__4550@7ebed7f2"]
;not helpful. it looks like I called a function. What did I call?
user=> (type increment-a-list)
clojure.core$map$fn__4549
;not helpful. what about the type of the garbage output?
user=> (type (increment-a-list [1,2,3]))
clojure.core$map$fn__4549$fn__4550
;not helpful. Though, I do know this is a transducer, whatever that means.
;Transducers can transduce, so let's go for it
user=> (transduce increment-a-list [1,2,3])
ArityException Wrong number of args (2) passed to: core/transduce clojure.lang.AFn.throwArity (AFn.java:429)
;my bad. it needs a "reducer" function
user=> (transduce increment-a-list + [1,2,3])
9
;aw sweet! [1,2,3] became [2,3,4] which in turn became (2+3+4) which is 9!!!
;let's level up. time to crush it. lemme implement a "last thing wins" reducer.
;here goes!
user=> (transduce increment-a-list (fn [a b] b) [1,2,3])
ArityException Wrong number of args (0) passed to: user/eval1217/fn--1218 clojure.lang.AFn.throwArity (AFn.java:429)
; yo what?
; it needs to be able to take 0 arguments, but presumably also 2 arguments
user=> (defn takes-zero-or-two
#_=> ([a b] b)
#_=> ([] 0))
#'user/takes-zero-or-two
;ok, got my new reducer. let's go
user=> (transduce increment-a-list takes-zero-or-two [1,2,3])
ArityException Wrong number of args (1) passed to: user/takes-zero-or-two clojure.lang.AFn.throwArity (AFn.java:429)
;this game is fun! add a third signature!
user=> (defn has-many-signatures
#_=> ([] 0) ([a] a) ([a b] b))
#'user/has-many-signatures
user=> (transduce increment-a-list has-many-signatures [1,2,3])
4
;booyah. last-one-wins, except the last-one came from the incremented list, so it's 4 and not 3!
;what about a 'first-guy-wins'?
user=> (defn leave-bucket-alone
#_=> ([] 0) ([a] a) ([a b] a))
#'user/leave-bucket-alone
user=> (transduce increment-a-list leave-bucket-alone [1,2,3])
0
;i guess that is expected. we call the reducer with zero-arity to get the seed, then we are using the 2-arity version.
;what's the point of the 1-arity version?
user=> (defn weird-handoff
#_=> ([] 1) ([a] (inc a)) ([a b] a))
#'user/weird-handoff
user=> (transduce increment-a-list weird-handoff [1,2,3])
2
;oh, so we call the 0-arity version, and then we put that value into the 1-arity version,
;and then, after _that_, we start using the 2-arity reduce the way reduce normally works.
;got it
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment