- 论坛徽章:
- 0
|
网上找到的这些内容:
当macro展开时会在当前的scope里引入新的symbol,而这些新引入的symbol会和原有的symbol同名,所谓capturing problem。而这种错误,因为在展开macro时产生的,所以程序员光看源代码很难察觉。
比如,你定义一个宏 or 如下:
(or e1e2) ---> (let ((v e1)) (if v v e2))
如果你的程序这样写 (or nil v), 展开后就是:
(or nil v) ---> (let ((v nil)) (if v v v))
原来“(or nil v)”中的v是free variable,但展开后就和macro中的binding variable v同名,成了bound variable。
早先的解决办法,只是展开macro时,把所有新的symbol都“篡改”一下,好比 v 改成 v0340。但这样只是减少了重名的可能,显然没有彻底解决问题,"不卫生"也。Hygienic macro(卫生宏)就是指不会产生这种capturing problem的宏展开机制。具体方法,感兴趣可以读 Hygienic Macro Expansion 这篇文章。
但是我还是不明白,我把R5RS翻来覆去的看,都快崩溃了,哪位高手指教一下,跪求!
如果用syntax-rules来写这个宏应该怎么写呢?又怎么避免这个问题呢?为什么可以避免这个问题呢?
R5RS里是这样的:
(define-syntax or
(syntax-rules ()
((or) #f)
((or test) test)
((or test1 test2 ...)
(let ((x test1))
(if x x (or test2 ...))))))
这里引入了变量x,那么,如果求值(or y x)会怎么样?为什么不会出现前面的类似问题?
是不是因为,syntax-rules不是简单的字面意义上的替换,所以可以避免前面的问题?是这样吗?
注意,这里最后一句不是写成 (if test1 test1 (or test2 ...),不是直接展开,
而是用x 替换了test1,用什么用意??????????? |
|