Archive

Archive for August, 2011

Briefly, the “arity-reduce” pattern in Clojure

August 20th, 2011

Update: As noted on Reddit, this pattern, as usual, is both old and well-known: induction or structural induction. Duh. :)

Update2:: Or catemorphism perhaps (see comments).


I think it’s a good policy to read as much source code as I write. Writing code will make you better, and you’ll even stumble across some genuinely good approaches to software. However, it’s hard to compete with closely studying other people’s code. With that in mind, I’ve been learning Clojure since late last year and making a point to read the source code for the standard library regularly. It’s really great code and I guess it’s idiomatic Clojure pretty much by definition (with the exception of some of the core preamble).

While exploring Clojure, there’s a pattern that I’ve encountered which I’ll call the “arity-reduce” pattern. If it has an official name, I’m not aware of it. In any case, I’ve seen it many times, but never seen it called out in books or blogs. It came up again today in a 4clojure problem so I figured I’d write it down.

To motivate things, let’s image we’re implementing clojure.core/max, which takes one or more numeric arguments and returns their maximum value. Here’s how I might have approached it when I started learning Clojure:

(defn my-max [x & more] 
  (if more 
    (let [y (first more)] 
      (recur (if (> x y) x y) (next more))) 
    x))

This works, but the meaning of the what we’re trying to accomplish is lost in the details of the implementation. Here’s the official implementation:

(defn max
  "Returns the greatest of the nums."
  {:added "1.0"}
  ([x] x)
  ([x y] (if (> x y) x y))
  ([x y & more]
   (reduce max (max x y) more)))

Note how nice and declarative this is. It basically describes the solution to the problem:

  • Given a single argument, return it
  • Given two arguments, return the greater
  • Given more arguments, take the max of the first two args, rinse and repeat.

Maybe I’m slow, but for me, this was an eye-opener. With Clojure I’ve had to learn that whenever I write an anonymous function for use in map or reduce, I should ponder whether a built-in function that does what I need already exists (this is especially true with using sets, maps, and keywords as functions). Similarly, I should always ask my self if multiple arities of the same function would be clearer than jamming the whole implementation into one.

Here are some places where this pattern is used in Clojure:

And a few more that are made clearer by multi-arity definitions although they don’t explicitly use reduce in the “more” case:

  • <, >, and the rest of the comparison functions
  • and
  • or
  • The .., ->, and ->> threading macros

Cheers and happy Clojuring!

clojure

Dorothy: Graphviz from the comfort of Clojure

August 12th, 2011

I’ve used Graphviz quite a bit in the past. When I did, I was almost always generating dot files from code; I never wrote them by hand other than to experiment with various Graphviz features. Well, string-slinging is a pain. Generating one language from another is a pain. So, inspired by Hiccup, I threw together Dorothy over the last couple evenings. It’s a Clojure DSL for generating DOT graph representations as well as rendering them to images.

For a few hours work, the documentation is pretty thorough, so I’ll leave off with one simple example which is translated from the Entity Relationship example in the Graphviz gallery. Any feedback or criticism is welcome and encouraged.

and here it is displayed in Dorothy’s simple built-in viewer:

Entity Relationship graph

clojure ,