Practical Common Lisp第8章:let内do-primes用macroexpand-1无法展开问题
为什么macroexpand-1无法展开let包裹的内部宏调用
macroexpand-1的设计逻辑是仅对传入表达式的最外层做单次宏展开:
- 只有当传入表达式的最外层操作符是宏的时候,才会执行一次展开,不会递归处理子表达式
- 你传入的表达式最外层是
let,而let是Common Lisp标准定义的特殊操作符,不属于宏,所以macroexpand-1会直接原封不动返回整个输入表达式,自然不会处理内部嵌套的do-primes4宏调用。
如何展开内部的do-primes4宏
你可以用以下两种常用方案处理:
- 方案1:使用SBCL提供的全量宏展开工具
sb-cltl2:macroexpand-all,它会递归遍历并展开表达式中所有嵌套的宏调用,示例代码如下:
(sb-cltl2:macroexpand-all '(let ((ending-value 0)) (do-primes4 (p 0 10) (incf ending-value p)) ending-value))
执行后就能看到do-primes4完整展开后的代码,直观观察到命名泄漏的问题。
- 方案2:单独提取内部的
do-primes4调用,单独传给macroexpand-1进行展开验证,适合快速核对单个宏的展开结果。
内容的提问来源于stack exchange,提问作者nucranium
相关产品推荐
相关产品推荐

