Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 816
anonymous Avatar asked Jan 03 '12 04:01

anonymous


2 Answers

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.

like image 135
danlei Avatar answered Oct 22 '22 23:10

danlei


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
like image 20
amalloy Avatar answered Oct 23 '22 00:10

amalloy