我在读/采取切实可行的Common Lisp工作。 我在关于Lisp的建立一个测试框架的章节。
我有功能“测试 - +”,如下实施,它的工作原理:
(defun test-+ ()
(check
(= (+ 1 2) 3)
(= (+ 5 6) 11)
(= (+ -1 -6) -7)))
请记住,我说, 它的工作原理 ,这就是为什么接下来是令人百思不得其解....
下面是一些代码,“测试 - +”是指:
(defmacro check (&body forms)
`(combine-results
,@(loop for f in forms collect `(report-result ,f ',f))))
(defmacro combine-results (&body forms)
(with-gensyms (result)
`(let ((,result t))
,@(loop for f in forms collect `(unless ,f (setf ,result nil)))
,result)))
(defmacro with-gensyms ((&rest names) &body body)
`(let ,(loop for n in names collect `(,n (gensym)))
,@body))
(defun report-result (value form)
(format t "~:[FAIL~;pass~] ... ~a~%" value form)
value)
现在,我一直在用煤泥macroexpand这些,一步一步做的(使用Ctrl-C RET,它被映射到macroexpand-1)。
因此,“检查”的“测试 - +”展开这一号召:
(COMBINE-RESULTS
(REPORT-RESULT (= (+ 1 2) 3) '(= (+ 1 2) 3))
(REPORT-RESULT (= (+ 5 6) 11) '(= (+ 5 6) 11))
(REPORT-RESULT (= (+ -1 -6) -7) '(= (+ -1 -6) -7)))
然后,宏观膨胀成这样:
(LET ((#:G2867 T))
(UNLESS (REPORT-RESULT (= (+ 1 2) 3) '(= (+ 1 2) 3)) (SETF #:G2867 NIL))
(UNLESS (REPORT-RESULT (= (+ 5 6) 11) '(= (+ 5 6) 11)) (SETF #:G2867 NIL))
(UNLESS (REPORT-RESULT (= (+ -1 -6) -7) '(= (+ -1 -6) -7))
(SETF #:G2867 NIL))
#:G2867)
而且它的代码,直接这句话,这是不行的上方。 如果我粘贴到REPL,我得到以下错误(我使用Clozure Common Lisp的):
未结合的变量:#:G2867 [条件类型未结合的可变的]
现在,如果我采取相同的代码,请更换一个变量名gensym如“X”,它工作得很好。
那么,我们如何解释以下惊喜:
在“测试 - +”宏观调控,要求这一切,工作正常。
在“结合,结果”的宏扩展宏不运行。
如果我从“相结合,结果”宏观扩张删除gensym,它的工作。
我可以推测的唯一的事情是,你不能使用代码包含与gensyms的字面用法。 如果是的话,为什么不呢,以及如何围绕一个工作? 如果这是不是说明,究竟是什么?
谢谢。