为什么不在let表单的词汇上下文中评估此表单

时间:2013-04-16 14:40:33

标签: emacs elisp lexical-scope

我正在尝试创建一个宏来创建一个带有S表达式的函数,并在fixture的词汇上下文中对它们进行求值。这是我写的宏:

(defmacro def-fixture (name bindings)
  "Return a function that takes the form to execute but is wrapped between a let of the bindings"
  `(defun ,(intern (symbol-name name)) (body)
     (let (,bindings)
       (unwind-protect
           (progn
             body)))))

但是当我运行它时,它似乎是在我提供的词汇上下文之外执行

(def-fixture test-fixture '(zxvf 1))

(test-fixture '(= zxvf 1))
let: Symbol's value as variable is void: zxvf

顺便说一下,我启用了变量词法绑定。关于我的错误是什么想法?

2 个答案:

答案 0 :(得分:2)

这与词法范围无关。您的宏调用扩展为:

(defun test-fixture (body)
  (let ((quote (zxvf 1)))
    (unwind-protect (progn body))))

这当然不是你想要的。我不相信(test-fixture '(= zxvf 1))表示您引用的错误(即variable is void)。相反,呼叫信号(void-function zxvf),因为它试图评估(zxvf 1)。永远不会评估(= zxvf 1)表达式,因为它已被引用。

您可能想尝试更多类似的内容:

(defmacro def-fixture (name bindings)
  "Return a macro that takes the form to execute but is wrapped between a let of the bindings"
  `(defmacro ,name (body)
     `(let (,',bindings)
        (unwind-protect
          (progn
            ,body)))))

然后将其用作:

(def-fixture test-fixture (zxvf 1))
(test-fixture (= zxvf 1))

答案 1 :(得分:1)

以下注释位于emacs manual

  

此外,defun或defmacro正文中的代码无法参考   周围的词汇变量。

可能是你的问题所在。

此外,我不知道您是否需要引用def-fixture的第二个参数。我使用macrostep包检查生成的宏,如果没有引号,结果似乎更好。