1

我正在尝试创建一个宏来创建一个函数,该函数采用 S 表达式并在夹具的词汇上下文中评估它们。这是我写的宏:

(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

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

4

2 回答 2

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))
于 2013-04-17T00:23:40.973 回答
1

以下注释在emacs 手册中:

此外,defun 或 defmacro 主体中的代码不能引用周围的词法变量。

这可能是你的问题。

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

于 2013-04-16T15:02:46.103 回答