O'Reilly logo

Clojure Programming by Brian Carper, Christophe Grand, Chas Emerick

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

In Detail: -> and ->>

To explore how macros work to solve real problems, let’s work up an alternative implementation of a commonly used macro in Clojure: ->, which is very similar to its cousin, ->>. Often called threading macros, these are included in clojure.core (with a number of derivatives with similar semantics in various third-party libraries), and are remarkably useful in cleaning up chained function calls and chained Java-interop method calls.

What we’d like to do is be able rewrite somewhat awkward code like this:

(prn (conj (reverse [1 2 3]) 4))

…and instead write code like this:

(thread [1 2 3] reverse (conj 4) prn)

This way, rather than reading code inside-out (which can be difficult with deeply nested calls), we can read our code sequentially, left-to-right as a series of successive actions: “Start with [1 2 3], reverse it, conj 4 onto it, then prn it.”

It’s not hard to envision a macro to do this. Given a series of forms, we’ll take the first form and insert it as the second item in the second form, then take the resulting form and insert it as the second item in the third form, and so on.

Additionally, if any form after the first is not already a list, let’s consider it a list of one item. This lets us avoid parens on single-argument functions like this:

(-> foo (bar) (baz))

and instead write:

(-> foo bar baz)

First, let’s write a simple utility function to ensure that a form is a seq.

(defn ensure-seq [x] (if (seq? x) x (list x))) (ensure-seq 'x) ;= (x) (ensure-seq '(x)) ;= ...

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required