Cover by Brian Carper, Christophe Grand, Chas Emerick

Safari, the world’s most comprehensive technology and business learning platform.

Find the exact information you need to solve a problem on the fly, or go deeper to master the technologies and skills you need to succeed

Start Free Trial

No credit card required

O'Reilly logo

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)) ;= ...

Find the exact information you need to solve a problem on the fly, or go deeper to master the technologies and skills you need to succeed

Start Free Trial

No credit card required