You know that key that nobody ever uses … ever? Well Clojure uses it, so get ready to start exercising some muscle memory! Clojure uses some different quoting syntax that gives the programmer more control over how and when symbols are evaluated, which is especially useful when writing macros.

The Quote '

Going back to the basics, the quote returns the unevaluated list that follows.

=> '(1 2 3 4 5)
(1 2 3 4 5)
=> '(1 2 3 (inc a) 5)
(1 2 3 (inc a) 5)

The Syntax Quote `

The syntax quote does basically the same thing as quote, except it’s a bit more explicit when referencing symbols.

=> `(1 2 3 (inc a) 5)
(1 2 3 (clojure.core/inc user/a) 5)

As we can see in this example, the syntax quote fully qualifies all our symbols to include their namespaces. This can be useful, as the name a (or any other symbol) may be used in other parts of our program that can conflict with what we expect of it.

The Unquote ~

When used within a syntax quote, unquote will evaluate the symbol or form that follows.

=> (def a 4)
#'user/a
=> `(1 2 3 a 5)
(1 2 3 user/a 5)
=> `(1 2 3 ~a 5)
(1 2 3 4 5)
=> `(1 2 3 ~(inc a) 5)
(1 2 3 5 5)

In our unquote examples, ~a evaluated to 4 in our final result, and ~(inc a) evaluated to 5. This is good to know because a lot of the time when writing macros, we actually want what’s inside a symbol, rather than the symbol itself.

The unquote will not work inside a regular quote, however. This is another way that the quote and syntax-quoting differ.

=> '(1 2 3 ~a 5)
(1 2 3 (clojure.core/unquote a) 5)

Unquote-Splicing ~@

unquote-splicing has one job, and it does it well. When used inside a syntax-quoted list, it will simply take the values in a collection and place them in the parent collection. Let’s compare unquote-splicing to unquote in these cases.

=> (def some-numbers [2 3])
#'user/some-numbers
=> `(1 ~some-numbers 4 5)
(1 [2 3] 4 5)
=> `(1 ~@some-numbers 4 5)
(1 2 3 4 5)

If we macroexpand this, we can see what’s really is Clojure’s is simply taking everything in the list and concat-ing them together into one list. Cool!

=> (macroexpand '`(1 ~@some-numbers 4 5))
(clojure.core/seq (clojure.core/concat (clojure.core/list 1) some-numbers (clojure.core/list 4) (clojure.core/list 5)))

;; And the simplified macroexpansion...
(seq (concat '(1) some-numbers '(4) '(5)))

Quote Debugging

Now that we have some of the different quoting syntax out of the way, let’s complicate things.

`~some-symbol

Can you imagine what this might be doing? Well, we’re syntax-quoting ~some-symbol. So if ~ just evaluates what follows when in a syntax quote, then what we should see is an evaluation of some-symbol. So `~ should behave like an identity (not to be confused with the identity function).

=> (def some-symbol "Cymbal")
#'user/some-symbol
=> `~some-symbol
"Cymbal"

`'~some-symbol

What we are looking at here is the syntax-quoted form, '~some-symbol. Since we are in a syntax-quoted form, we can go ahead and evaluate ~some-symbol and what we should see is its quoted value.

=> `'~some-symbol
(quote "Cymbal")

A lot of this can seem confusing at first, but once you get a handle on what each quote does, it becomes easier to predict how it will behave when in the presence of other quotes.