- 論壇徽章:
- 0
|
網(wǎng)上找到的這些內(nèi)容:
當macro展開時會在當前的scope里引入新的symbol,而這些新引入的symbol會和原有的symbol同名,所謂capturing problem。而這種錯誤,因為在展開macro時產(chǎn)生的,所以程序員光看源代碼很難察覺。
比如,你定義一個宏 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。但這樣只是減少了重名的可能,顯然沒有徹底解決問題,"不衛(wèi)生"也。Hygienic macro(衛(wèi)生宏)就是指不會產(chǎn)生這種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)會怎么樣?為什么不會出現(xiàn)前面的類似問題?
是不是因為,syntax-rules不是簡單的字面意義上的替換,所以可以避免前面的問題?是這樣嗎?
注意,這里最后一句不是寫成 (if test1 test1 (or test2 ...),不是直接展開,
而是用x 替換了test1,用什么用意??????????? |
|