代码之家  ›  专栏  ›  技术社区  ›  mobiuseng

Common Lisp中的后引号:read和eval

  •  5
  • mobiuseng  · 技术社区  · 10 年前

    这个问题有点重复了 this this for Elisp 。基本上,如何阅读和评估后引号?正在发生什么过程?标准对此有什么规定吗?

    这是我所期望的,但是 这不会发生 :symbol `是一个读取器宏,并被转换为某种 (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))
    

    与预期有所不同,但好吧。现在, ,C 是一只有趣的野兽:

    CL-USER> (type-of (third (cadr *q*)))
    SB-IMPL::COMMA
    

    如果没有逗号符号,则可以计算读取表达式:

    CL-USER> (eval (read-from-string "`(a b c)"))
    (A B C)
    

    但是,如果我想对原始表达式进行求值 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}>.
    

    这意味着 EVAL 没有接受 C 已绑定。

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

    1 回复  |  直到 9 年前
        1
  •  14
  •   Rainer Joswig mmmmmm    10 年前

    后引号

    Backquote 是一个标准 macro character 在Common Lisp中。

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

    评估

    你遇到的问题 eval 与读取器或反引号表达式完全无关:

    ? (let ((c 10))
        (eval '(list 'a 'b c)))
    
    Error: The variable C is unbound.
    

    通用Lisp EVAL 正在使用动态环境和 null lexical environment 用于评估表格。高于词汇环境,其中 c 被绑定到 10 ,未使用。

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

    ? (let ((c 10))
        (declare (special c))
        (eval '(list 'a 'b c)))
    (A B 10)
    

    因此,这同样有效:

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

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