2

这是我的宏定义:

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

现在一切正常,所以我定义了第二个宏(运行多个测试):

*(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)

这个结果不是我想要的,我希望每个值都tc被 sexp 替换,并在运行测试中评估该值。我试图更换线路

          do (run-test tc)

          do (run-test ,tc)

但这表示错误

未定义变量:TC

我怎样才能改变它以获得正确的结果?

4

2 回答 2

10

看看 eg 的展开(run-tests (= 1 1))

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

如您所见,代码尝试调用(run-test tc). 而是run-test在表单上操作;当您传递包含表单的变量时,它将不起作用。

如果您将代码更改为(run-test ,tc)您试图tc在宏扩展期间引用该变量,但它仅在运行时绑定。

一种解决方案是在宏扩展时做更多的事情:

(defmacro run-tests (&body body)
  `(progn ,@(loop for tc in body collect `(run-test ,tc))))
于 2013-10-15T05:40:27.810 回答
0

就像练习一样。你可以摆脱宏:

(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)))
于 2013-10-15T10:13:03.053 回答