Common Lisp中的反引用:read和eval

mob*_*eng 3 lisp elisp common-lisp reader-macro

这个问题在一定程度上重新接种到这个这个对elisp的.基本上,如何读取和评估反向报价?正在发生什么过程?标准是否对此有所说明?

这是我所期望的,但它不会发生:符号`是一个读者宏 - 并被翻译成某种(BACKQUOTE ...)宏/特殊形式(类似于'被翻译(QUOTE ...)).这不会发生,事实上,Common Lisp甚至没有BACKQUOTE宏.

发生了什么(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))
Run Code Online (Sandbox Code Playgroud)

与预期有所不同,但还可以.现在,,C它本身就是一个有趣的野兽:

CL-USER> (type-of (third (cadr *q*)))
SB-IMPL::COMMA
Run Code Online (Sandbox Code Playgroud)

如果没有逗号符号,则评估读取表达式是正常的:

CL-USER> (eval (read-from-string "`(a b c)"))
(A B C)
Run Code Online (Sandbox Code Playgroud)

但是如果我想用本地绑定来评估原始表达式C,则存在一个问题:

(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}>.
Run Code Online (Sandbox Code Playgroud)

这意味着EVAL没有拿起C绑定的环境.

PS.有趣的是,在Elisp中这是有效的.

Rai*_*wig 11

反引号

Backquote是Common Lisp中的标准宏字符.

在Common Lisp中,反引号表达式的表示是未定义的.实现实际上使用不同的表示.您对SBCL的看法是特定于实现的.

EVAL

使用eval时遇到的问题与读者或反引号表达式完全无关:

? (let ((c 10))
    (eval '(list 'a 'b c)))

Error: The variable C is unbound.
Run Code Online (Sandbox Code Playgroud)

Common Lisp EVAL使用动态环境和null词法环境来评估表单.上述词汇的环境下,c势必会10,不使用.

但动态绑定是.我们需要将变量声明为 special:

? (let ((c 10))
    (declare (special c))
    (eval '(list 'a 'b c)))
(A B 10)
Run Code Online (Sandbox Code Playgroud)

因此,这也有效:

? (let ((c 10))
    (declare (special c))
    (eval (read-from-string "`(a b ,c)")))
(A B 10)
Run Code Online (Sandbox Code Playgroud)

默认情况下,Emacs Lisp具有动态绑定(尽管GNU Emacs现在也支持词法绑定).Common Lisp默认具有词法绑定.