Clojure refactoring: flattening reduces

mistakes — cgrand, 19 January 2010 @ 12 h 48 min

This morning I wrote some code which looked like:

(reduce (fn [acc x]
          (reduce (fn [acc y]
                    (reduce f acc y)) acc x)) init xs)

(it was slightly more complex with some filtering and destructuring thrown in for good measure).

I wasn’t happy with those nested reduces and it occured to me that I could refactor it to use a single one:

(reduce f init (for [x xs, y x, z y] z))

Now that reads better!

8 Comments »

  1. OK, please keep this sort of thing to yourself. You’re scaring people. :) (see: http://search.twitter.com/search?q=too+stupid+to+program+in+clojure )

    I’m kidding, but one of the reasons I love Clojure is that it’s deeply practical for problems that don’t resolve to math functions. Some elaboration might benefit this example. I guess you have a sequence of sequences of sequences and want to reduce f over all values contained therein? (where values are always in the innermost sequences only)

    Thanks for the blog!

    Comment by Jeremey — 19 January 2010 @ 21 h 07 min
  2. Took me a sec to figure out what you’re doing but that is freakin’ awesome. Will have to remember it in the future.

    Comment by Patrick Sullivan — 19 January 2010 @ 21 h 17 min
  3. @Jeremey: it was a seq of maps of sets (which I could have obtained from a database) and the computation used values of the sets and keys of the maps.

    Comment by cgrand — 19 January 2010 @ 21 h 23 min
  4. That’s just awesome, really neat code!

    I used to write something like this: (clojure.contrib.seq-utils/flatten (apply concat (map seq foo))) instead of (for [x foo, y x, z y] z), I don’t use ‘for’ enough.

    Comment by Nicolas Buduroi — 20 January 2010 @ 1 h 50 min
  5. [...] all the examples, you’re seeing the power of the seq-abstraction. Lets say you need to work on a nested strucuture, only working on the innermost data — double bound for is your friend. Imagine you have a [...]

    Pingback by Simplicity on Steroids | BEST IN CLASS — 4 February 2010 @ 22 h 29 min
  6. Very neat way to flatten sequence of sequences! I would usually do something like what Nicolas did, but this way is much better. Thank you for posting it!

    Comment by Ivan Koblik — 27 February 2010 @ 22 h 34 min
  7. Thanks for writing this idiom up. I had a need for just such an idiom today and instead of a lot of small nested reduces I used the a for form to handle it all.

    Comment by William Hidden — 7 April 2010 @ 16 h 24 min
  8. Same for me: just needed this and luckily remembered this post. You should rename your blog to “Treasure Chest” or so. :)

    Comment by Meikel — 30 April 2010 @ 11 h 55 min

RSS feed for comments on this post. TrackBack URI

Leave a comment

(c) 2010 Clojure and me | powered by WordPress with Barecity