Clojure: The subtle difference between quote (‘) and backtick (`)
The code presented here is available on github .
The obvious parts
You’ll be aware of these if you’ve ever bothered writing macros:
- Both prevent evaluation of the subsequent expression:
`(1 2 3) ;; => (1 2 3) '(1 2 3) ;; => (1 2 3)
- Backtick allows you to unquote parts of the expression:
(def x 3) `(1 2 ~x) ;; => (1 2 3) '(1 2 ~x) ;; => (1 2 (clojure.core/unquote x))
As you can see, quote does not interpret the tilde character (which is just a reader macro for clojure.core/unquote).
- …or even additionally splice a sequence:
(def y (list 3 4)) `(1 2 ~@y) ;; => (1 2 3 4) '(1 2 ~@y) ;; => (1 2 (clojure.core/unquote-splicing y))
Same thing here – quote does not do anything with the “~@” reader macro, as it is just an alias for clojure.core/unquote-splicing.
The subtle part
- However, quote and backtick show different behavior in how they handle namespace resolution for the symbols they quote:
(def z 111) `(1 2 z) ;; => (1 2 user/z) '(1 2 z) ;; => (1 2 z)
So why is this relevant?
Well, consider the following code. The essence of this is that we have a namespace macro-ns in which macros get defined. Those macros are being used in another namespace (user here):
(in-ns 'macro-ns) (clojure.core/use 'clojure.core) (def z 222) (defmacro m-quote [] 'z) (defmacro m-backtick [] `z) ;; Now, we'll want to use these macros in the "user" namespace: (in-ns 'user) (def z 111) (macroexpand-1 '(macro-ns/m-quote)) ;; => z (macroexpand-1 '(macro-ns/m-backtick)) ;; => macro-ns/z (macro-ns/m-quote) ;; => 111 (macro-ns/m-backtick) ;; => 222
So obviously it does matter whether you use quote or backtick in a macro, even if you don’t intend to use any unquoting within. As you can see above, m-quote refers to user/z, while m-backtick results in an expansion that uses macro-ns/z.