Getting to Know Macros, Part 2

Malina Tran
Tech and the City
Published in
3 min readJul 26, 2016
This book is great! All of my blog posts are summaries of each chapter.

Let’s hit the ground running! We’ve established some key attributes of a “macro.” You can think about macros are shortcut functions (they are found across programming languages) and allow Clojure to create a suite of built-in functions special forms. Macros are a way of transforming a data structure into a form Clojure can evaluate. I had assumed that macros were an advanced topic, something you use when getting fancy, but it’s so commonly used that writing a macro seems to be at the core of writing Clojure. In Clojure, `when`, `and`, and `or` are defined as macros! Makes sense, right? After all, they help extend the language further so it meets your code base’s needs.

Macro definitions look much like function definitions. Here’s the anatomy of a function: name, optional document string (this is the line of text that explains the function), argument list, and a body. The body will almost always return a list. Macros are called just like a function or special form — you can also use argument destructuring, `let` bindings, multiple-arity and recursion! The key difference between functions and macros is that function definitions are fully evaluated before they’re passed to the function, whereas macros receive arguments as unevaluated data.

Clojure for the Brave and True provides a really good example. Say we want to create a macro that takes an expression and prints and return its value. In the code below, there are several issues with this attempt. The first being that the macro body tries to get the value that the symbol `let` is referring to, whereas we’re just trying to return the `let` symbol itself (as seen in the last line). We’re trying to get the value of `result` which isn’t bound and the value of `println` which is returning its symbol.

(defmacro my-print-which-is-wrong
[expression]
(list let [result expression]
(list println result)
result))

Here is a revision of the above. You’ll notice that we are quoting each symbol by prefixing it with a single quote character. This “turns off” evaluation and returns the symbol, rather than tries to resolve it.

(defmacro my-print
[expression]
(list 'let ['result expression]
(list 'println 'result)
'result))

And then there’s syntax quoting (`), which returns unevaluated data structures (so it’s similar to single quotes). However, syntax quoting allows you to:

  1. Return the fully qualified symbols, with the symbol’s namespace included (example below)
  2. Do something similar to string interpolation (e.g. create a template, place a few variables within a larger, static structure).
`(+ 1 2)
; => (clojure.core/+ 1 2)
`(+ 1 (inc 1))
; => (clojure.core/+ 1 (clojure.core/inc 1))

Using syntax quoting is much more succinct than single quoting and you can exempt anything from being quoted with a ~. There’s also an unquote splicing technique, which is called with a ~@, and its role is to unwrap a data structure and place its contents directly within the syntax-quoted data structure. This quote (not single nor syntax — but from Daniel Higginbotham himself) is pretty awesome: “It’s like the ~@ is a sledgehammer and whatever follows it is a piñata, and the result is the most terrifying and awesome party you’ve ever been to.” Again, an example is probably warranted:

`(+ ~(list 1 2 3))
; => (clojure.core/+ (1 2 3))
`(+ ~@(list 1 2 3))
; => (clojure.core/+ 1 2 3)

All in all, some key takeaways include: macros will almost always return lists and syntax quote allows writing macros (and will be used most of the most over `list` and `seq` functions).

--

--