logoalt Hacker News

eductionyesterday at 5:43 PM2 repliesview on HN

Canonical example is rewriting a non transducing set of collection transformations like

   (->> posts
      (map with-user)
      (filter authorized?)
      (map with-friends)
      (into []))
That’s five collections, this is two, using transducers:

    (into []
          (comp
            (map with-user)
            (filter authorized?)
            (map with-friends))
          posts)
A transducer is returned by comp, and each item within comp is itself a transducer. You can see how the flow is exactly like the double threading macro.

map for example is called with one arg, this means it will return a transducer, unlike in the first example when it has a second argument, the coll posts, so immediately runs over that and returns a new coll.

The composed transducer returned by comp is passed to into as the second of three arguments. In three argument form, into applies the transducer to each item in coll, the third argument. In two argument form, as in the first example, it just puts coll into the first argument (also a coll).


Replies

kccqzyyesterday at 5:57 PM

That does not sound like a good example. The two-argument form of `map` already returns a lazy sequence. Same for `filter`. I thought lazy sequences are already supposed to get rid of the performance problem of materializing the entire collection. So

show 1 reply
fud101yesterday at 6:36 PM

Thanks. So is this not an optimiser Clojure runtime can do for you automatically? I find the first one simpler to read and understand.

show 1 reply