Question

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.
Était-ce utile?

La solution

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.

Autres conseils

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top