简体   繁体   English

在宏中取消引用时未定义的变量

[英]Undefined variable while unquoting in macro

Here is my macro definition: 这是我的宏定义:

*(defmacro run-test (test)
   `(format t "Run test ~a ... ~a" ',test ,test))
*(run-test (= 1 1))
Run test (= 1 1) ... T
NIL

Everything works fine for now, so I've defined a second macro (to run multiple tests): 一切都工作正常,所以我已经定义了第二个宏(运行多个测试):

*(defmacro run-tests (&body body) 
   `(loop for tc in ',body 
      do (run-test tc)))
* (run-tests (= 2 (1+ 1)) (= 1 1))
Run test TC ... (= 2 (1+ 1) Run test TC ... (= 1 1)

This result is not I wanted, I wanted each value of tc to be replaced by the sexp and the value be evaluated in run-test. 这个结果不是我想要的,我希望tc每个值都被sexp替换,并且在run-test中评估值。 i tried to replace the line 我试图更换线路

          do (run-test tc)

with

          do (run-test ,tc)

but this signals an error 但这表示错误

Undefined variable: TC 未定义的变量:TC

How can I change this to get the right result? 如何更改以获得正确的结果?

Look at the expansion of eg (run-tests (= 1 1)) : 看看例如(run-tests (= 1 1))的扩展:

(loop for tc in '((= 1 1)) do (run-test tc))

As you can see, the code tries to call (run-test tc) . 如您所见,代码尝试调用(run-test tc) But run-test operates on a form; run-test在表单上run-test ; it will not work when you pass a variable containing a form. 传递包含表单的变量时,它将不起作用。

If you change your code to (run-test ,tc) you are trying to refer to the tc variable during macroexpansion time, but it's only bound at runtime. 如果将代码更改为(run-test ,tc) ,则在宏扩展时尝试引用tc变量,但它仅在运行时绑定。

One solution would be to do more at macroexpansion time: 一个解决方案是在宏扩展时做更多的事情:

(defmacro run-tests (&body body)
  `(progn ,@(loop for tc in body collect `(run-test ,tc))))

Just as an exercise. 就像练习一样。 You could get rid of the macros: 你可以摆脱宏:

(defun run-test (test)
  (format t "~%Run test ~a ... ~a" test (eval test)))

(defun run-tests (tests)
  (mapc 'run-test tests)
  (values))

* (run-tests '((= 2 (1+ 1))
               (= 1 1)))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM