2012-04-23 42 views
6

使用reifyeval很容易在Scala中編寫衛生宏。但it's not always possible使用reifyeval在沒有通知的情況下確保衛生

因此,如果一個人不能使用它們,那麼確保宏觀衛生的規則是什麼?有沒有什麼方法可以測試一個宏,以確保沒有不良的衛生通過裂縫溜走?

upd。在後來的2.10.0里程碑中,Expr.eval被重命名爲Expr.splice

+0

閱讀[Wikipedia> Hygienic macro](http://en.wikipedia.org/wiki/Hygienic_macro)可能會有幫助。我沒有太多的宏經驗,所以我能做的最好的是重新維護Wikipedia的信息。 – 2012-04-23 16:11:30

+0

是的 - 我熟悉以前的Lisp和C++宏。但是,用一種語言工作的東西並不一定直接連接到另一種語言:-) – 2012-04-23 21:17:25

回答

10

Reify是衛生的,因爲它將符號與Ident和This樹一起保存。

如果您的宏擴展結果沒有附加到idents的符號(例如,您只有Ident(「x」)來指定對某個名爲x)的引用),則隨後的宏擴展的類型檢查將綁定x到任意在調用網站的範圍內(或者如果該範圍沒有x,則會收到編譯錯誤)。

相比之下,當您的宏擴展具有它的idents的符號時,typechecker不會嘗試重新解析它們,並且只是使用它的內容。這意味着,當您通過表達式並在宏展開中使用結果時,它會將其符號帶入呼叫站點。好吧,不是所有的符號,例如不可能引用局部變量或私有/受保護的東西,但是對全局可訪問的聲明的引用是持久的。

底線是檢查你的宏是否衛生,檢查你​​的idents和thises是否有附加符號。您可以通過編制或手動將符號分配給手工製作的樹木來實現此目的。

1

由於reify是一個宏,我只是看它的實現來找出它的作用。

+0

當然 - 這將是我的下一步行動:-)我不確定我會「只是」看看它 - 實現是相當的參與,並會採取一些分手。 鑑於沒有人似乎有任何規則可以處理,我想我會看看我是否可以捕獲它們,並在我這樣做時發佈它們。 – 2012-04-23 21:21:38

相關問題