在 Practical Common Lisp 的第 8 章“堵漏”中,我们定义了这个宏,并通过检查发现它泄漏了macroexpand-1
(defmacro do-primes ((var start end) &body body)
`(do ((,var (next-prime ,start) (next-prime (1+ ,var)))
(ending-value ,end))
((> ,var ending-value))
,@body))
由于此泄漏,以下看似无辜的 do-primes 调用无法正常工作:
(do-primes (ending-value 0 10) (print ending-value)) 这个也不是:
(let ((结束值 0)) (do-primes (p 0 10) (incf 结束值 p)) 结束值)
我可以macroexpand-1
像这样使用它,我将这个宏命名为 do-primes4
(macroexpand-1 '(do-primes4 (ending-value 0 10)
(print ending-value)))
(DO ((ENDING-VALUE (NEXT-PRIME 0) (NEXT-PRIME (1+ ENDING-VALUE)))
(ENDING-VALUE 10))
((> ENDING-VALUE ENDING-VALUE))
(PRINT ENDING-VALUE))
但是我不能在第二种形式上做同样的事情,其中宏调用是用 let
(macroexpand-1 '(let ((ending-value 0))
(do-primes4 (p 0 10)
(incf ending-value p))
ending-value))
(LET ((ENDING-VALUE 0))
(DO-PRIMES4 (P 0 10)
(INCF ENDING-VALUE P))
ENDING-VALUE)
它似乎实际上并没有对 do-primes4 进行宏扩展。我正在使用 SBCL。