在实用的通用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))(以下看似无辜的呼吁)-primes由于泄漏而无法正常工作:
(do-素数(结束值0 10) (打印结束值-值))这一项也不是:(let ((结束值0)) (do-素数(p 0 10) (incf结束值p))结束值)
我可以在这样的地方使用macroexpand-1,我已经将这个宏命名为
(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)它似乎并不是真正的宏观扩张做前4。我用的是SBCL。
发布于 2021-11-21 17:15:39
有两个宏扩展函数,macroexpand和macroexpand-1、http://clhs.lisp.se/Body/f_mexp_.htm.这两个扩展宏,macroexpand-1做一个级别,macroexpand继续进行直到它被完全展开。两者都返回两个值:
宏观扩展如下:
; macro expansion
(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))
; flag
T首先打印展开,然后再打印标志--这里是T,以显示展开发生了。
第二个例子的问题是,let是宏扩展中的第一个项目。目前,您只尝试展开let表单,其主体未更改地返回:
(macroexpand-1 '(let ((ending-value 0)) (do-primes4 (ending-value 0 10)
(print ending-value))))
(LET ((ENDING-VALUE 0))
(DO-PRIMES4 (ENDING-VALUE 0 10)
(PRINT ENDING-VALUE)))
NIL该标志接受值NIL,以显示没有展开。
let窗体扩展到自身,因为它不是带有标志NIL的宏
CL-USER> (macroexpand-1 '(let ((x 0))))
(LET ((X 0)))
NIL发布于 2021-11-22 11:46:28
虽然,正如Rainer所指出的,在这种情况下,您需要一个代码遍历器来查看扩展的实际内容,而且macroexpand-1多的macroexpand都不是代码遍历者,但是您实际上并不需要这样做来查看这里的问题所在。以类似的形式
(let ((ending-value 0))
(do-primes (p 0 10)
(incf ending-value p))
ending-value)您只需在顶层展开do-primes表单,然后替换它,得到明显的结果:
(let ((ending-value 0))
(do ((p (next-prime 0) (next-prime (1+ p))) (ending-value 10))
((> p ending-value))
(incf ending-value p))
ending-value)现在马上就可以看出问题是什么:您正在递增的ending-value不是您认为的绑定。
有各种各样的CL代码-步行者在那里:我不太熟悉他们推荐一个。
https://stackoverflow.com/questions/70056233
复制相似问题