简体   繁体   中英

Clojure - Quoting Confusion

Sorry for the terribly vague title :)

I am new to macros and am having trouble understanding the difference between these two statements:

`(+ 1 2 ~(+ 2 3)) ; => (clojure.core/+ 1 2 5)
'(+ 1 2 ~(+ 2 3)) ; => (+ 1 2 (clojure.core/unquote (+ 2 3)))

When I run them without the unquote, they seem rather identical other than qualifying?

`(+ 1 2 (+ 2 3)) ; => (clojure.core/+ 1 2 (clojure.core/+ 2 3))
'(+ 1 2 (+ 2 3)) ; => (+ 1 2 (+ 2 3))

So basically I'm confused by ` vs '. My understanding is that they both quote everything in the list, which is why I'm not sure why unquoting behaves differently. Basically ` behaves the way I would expect both ` and ' to behave.

Thanks!

The short answer is, that unquoting only works inside a backquote. In a normal quoted expression, everything – included ~ and everything inside/behind – is just passed as-is, while inside a backquoted expression, everything inside/behind ~ is evaluated (but everything else stays unevaluated). So, no, not everything inside a backquoted expression remains unevaluated – you can use ~ inside it, to use it as a kind of template, where you "fill in the blanks" with ~ .

Edit: To quote (pun intended) the documentation relevant to your question:

Quote:

Quote (')
'form => (quote form)

and (from the special forms section):

(quote form) Yields the unevaluated form.

user=> '(a b c)
(a b c)

Note there is no attempt made to call the function a. The return value is a list of 3 symbols.

Syntax-quote (also called quasiquote, backquote):

For Lists/Vectors/Sets/Maps, syntax-quote establishes a template of the corresponding data structure. Within the template, unqualified forms behave as if recursively syntax-quoted, but forms can be exempted from such recursive quoting by qualifying them with unquote or unquote-splicing, in which case they will be treated as expressions and be replaced in the template by their value, or sequence of values, respectively.

Try running eval on the results of your first two expressions. The first one, with `, "expands" to (+ 1 2 3) , which nicely evaluates to 6. The second, with ', "expands" to (+ 1 2 (unquote (+ 1 2))) , and unquote is not valid in that context since you're no longer inside of a quote! So this completely fails to evaluate at all.

Basically there are two differences between ' and `:

  • ` namespace-qualifies everything
  • ` allows unquoting

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM