This question is somewhat replated to this and this for Elisp. Basically, how is the back-quote read and evaluated? What processes are happening? And does the standard say anything about it?
Here is what I would expect, but it doesn't happen: symbol ` is a reader-macro and is translated into some kind of (BACKQUOTE ...)
macro/special form (similarly to '
being translated to (QUOTE ...)
). This doesn't happen, and, in fact, Common Lisp doesn't even have a BACKQUOTE
macro.
What is happening (SBCL):
CL-USER> (defparameter *q* (read-from-string "`(a b ,c)"))
*Q*
CL-USER> *q*
`(A B ,C)
CL-USER> (car *q*)
SB-INT:QUASIQUOTE
CL-USER> (cdr *q*)
((A B ,C))
Something different from expected, but OK. Now, ,C
is an interesting beast on its own:
CL-USER> (type-of (third (cadr *q*)))
SB-IMPL::COMMA
If there are no comma-symbols, evaluating the read expression is fine:
CL-USER> (eval (read-from-string "`(a b c)"))
(A B C)
But if I want to evaluate the original expression even with local binding for C
, there is a problem:
(let ((c 10)) (eval (read-from-string "`(a b ,c)")))
; in: LET ((C 10))
; (LET ((C 10))
; (EVAL (READ-FROM-STRING "`(a b ,c)")))
;
; caught STYLE-WARNING:
; The variable C is defined but never used.
;
; compilation unit finished
; caught 1 STYLE-WARNING condition
; Evaluation aborted on #<UNBOUND-VARIABLE C {1007A3B2F3}>.
This means that EVAL
didn't pick up the environment in which C
is bound.
PS. Interestingly enough, in Elisp this works.
Backquote
Backquote is a standard macro character in Common Lisp.
In Common Lisp the representation of a backquote expression is undefined. Implementations actually use different representations. What you see for SBCL is implementation specific.
EVAL
The problem you have with eval is fully unrelated to the reader or backquote expressions:
? (let ((c 10))
(eval '(list 'a 'b c)))
Error: The variable C is unbound.
In Common Lisp EVAL
is using the dynamic environment and the null lexical environment for evaluation of forms. Above lexical environment, where c
is bound to 10
, is not used.
But the dynamic binding is. We need to declare the variable to be special
:
? (let ((c 10))
(declare (special c))
(eval '(list 'a 'b c)))
(A B 10)
Thus this works, too:
? (let ((c 10))
(declare (special c))
(eval (read-from-string "`(a b ,c)")))
(A B 10)
Emacs Lisp had/has dynamic binding by default (though GNU Emacs now also supports lexical binding). Common Lisp has lexical binding by default.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With