这是我的宏定义:
*(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
如何更改此选项以获得正确的结果?
答案 0 :(得分:10)
看看例如(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))))
答案 1 :(得分: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)))