Jisang Yoo
Jisang Yoo

Reputation: 3745

nesting backquote and ` in emacs lisp

There seems to be some difference between short backquote and long backquote.

(let ((x 123))
  (dolist (res (list `(a `(b ,x))
                     `(a (backquote (b ,x)))
                     (backquote (a (backquote (b ,x))))
                     (backquote (a `(b ,x)))))
    (print res)))

Output:

(a (\` (b (\, x))))

(a (backquote (b 123)))

(a (backquote (b 123)))

(a (\` (b (\, x))))

Why does it behave differently as to x? Not even sure which two of the four results are supposed to be the surprising results.

Upvotes: 10

Views: 1317

Answers (1)

Diego Sevilla
Diego Sevilla

Reputation: 29011

I'm not sure if it is a bug or a feature, mainly because I'm not sure if a elisp programmer is allowed/good practice to use the backquote function, or it is just a convenient way of defining the function. The correct output is the first (and fourth) output. Looking at the code for backquote (in backquote.el) it is clear that any backquote inside either a ` or backquote is not properly expanded. The relevant code for this is:

   ((eq (car s) backquote-backquote-symbol)
      (backquote-delay-process s (1+ level)))

where backquote-backquote-symbol is defined before as '\` (quote-backslash-backtick). There are several ways of treating this error, but the line could be then:

   ((or (eq (car s) backquote-backquote-symbol)
        (eq (car s) 'backquote))
      (backquote-delay-process s (1+ level)))

(or using any other variable for specifying the backquote unaliased symbol).

EDIT: Looking at it more closely, there is another place where you have to add that test too, but this includes reporting a patch. I'll see how do I do it. With that change:

ELISP> (macroexpand-all `(a (backquote (b ,x))))
(a
 (list 'b x))
ELISP> (macroexpand-all `(a `(b ,x)))
(a
 (list 'b x))

Upvotes: 4

Related Questions