Clojure - difference between ' (apostrophe) and ` (backtick)
Asked Answered
U

2

47

I'm fairly new to Clojure and I'm not sure I completely understand the difference between apostrophe and backtick in Clojure.

(def x 5)

;; Question 1
(+ x x)  ;; evaluates to 10
'(+ x x) ;; evaluates to (+ x x)
`(+ x x) ;; evaluates to (clojure.core/+ user/x user/x)

;; Question 2
`(~+ ~x ~x) ;; evaluates to (#<core$_PLUS_ clojure.core$_PLUS_@32ee28a9> 5 5)
  1. Correct me if I'm wrong, but it seems to me that apostrophe prevents all symbols (i.e + and x) from resolving to their respective var's, whereas backtick allows the symbols to resolve to their var's (but doesn't evaluate to the values within the var). Is this accurate?
  2. What exactly does the unquote symbol (~) do here? Is it eval'ing the var to its actual value (i.e. the + symbol to the function object and the x symbol to the number object)? If you could explain this in terms of Clojure's READ-COMPILE-EVAL phases, that would be helpful as well.
Unconventional answered 23/7, 2013 at 3:14 Comment(0)
U
43

When you quote a collection with ', the symbol-name will be quoted exactly as you enter it.

'(+ x x) 
=> (+ x x)
(map namespace *1)
=> (nil nil nil)
'(bingo/+ lara/y user/z)
=> (bingo/+ lara/y user/z)
(map namespace *1)
=> ("bingo" "lara" "user")

When you quote a collection with the backtick, it tries to find each symbol's namespace. If it can't find one, it uses the current namespace. If you specify a namespace, it works the same as ' with a qualified namespace.

`(+ x x)
= > (clojure.core/+ user/x user/x)
(map namespace *1)
=> ("clojure.core" "user" "user")

When you are using ~ inside ` the form will simply be unquoted. This is helpful for building macros where the macro uses symbols from the namespace it is defined in as well as symbols from the namespace where it is used.

 `(+ ~'x x)
 => (clojure.core/+ x user/x)
 `(+ ~x x)
 => (clojure.core/+ 3 user/x)

Finally, you can unquote a whole collection of quoted things splicing.

 `(+ ~@`(x x))
 => (clojure.core/+ user/x user/x)

See both xes could have been passed as a list of namespace-qualified symbols and would have been spliced into another list. You can not use ~ or ~@ outside of a backtick-quoted collection.

Ubiquitous answered 23/7, 2013 at 12:36 Comment(2)
Nice answer. There's an excellent blog post here if you want to dig deeper: blog.8thlight.com/colin-jones/2012/05/22/…Haveman
See all those examples live with KLIPSE app.klipse.tech/…Ogdon
H
2

Backquote is a syntax-quote in Clojure terms, see its description at http://clojure.org/reader .

During reading, `(~+ ~x ~x) expands to form that generates list that can refer to lexical environment. Then compiler compiles this code. Let's see what `(~+ ~x ~x) expands to, prepending it with a quote:

user=> '`(~+ ~x ~x)
(clojure.core/seq (clojure.core/concat (clojure.core/list +) (clojure.core/list x) (clojure.core/list x)))

If you just insert this form in text editor instead of `(~+ ~x ~x), it will build list with + function and two x's. So, `(~+ ~x ~x) expands to Clojure code that builds list of particular structure.

Backquote is kind of template language for Clojure data (lists, arrays etc).

Hairsplitting answered 23/7, 2013 at 3:56 Comment(4)
What does "syntax-quote" actually mean?Unconventional
It is a just a word in Clojure documentation. See also #3704872Hairsplitting
it means quote, but having resolved symbols first: '+ means just '+', whereas `+ means 'clojure.core/+', but if you said (def + rest), then `+ becomes 'user/+' - so it's what the symbol resolves to in the environmentRijeka
Markdown problem: there's at least one unescaped backtick in this answer causing trouble.Kuopio

© 2022 - 2024 — McMap. All rights reserved.