reify
とを使用すると、Scalaで衛生的なマクロを簡単に作成できますeval
。ただし、とを常に使用できるreify
とは限りませんeval
。
それで、それらを使用できない場合、マクロが衛生的であることを保証するルールは何ですか?そして、マクロをテストして、悪い衛生状態が亀裂をすり抜けていないことを確認する方法はありますか?
upd。2.10.0のその後のマイルストーンで、名前Expr.eval
がに変更されましたExpr.splice
。
Reifyは、IdentおよびThisツリーとともにシンボルを保存するため、衛生的です。
マクロ展開の結果にIDにシンボルが付加されていない場合(たとえば、xという名前の参照を指定するIdent( "x")だけがある場合)、マクロ展開の後続のタイプチェックにより、xはスコープ内にあるものにバインドされます。呼び出しサイト(または、そのスコープにxがない場合は、コンパイルエラーが発生します)。
対照的に、マクロ展開にIDの記号がある場合、typecheckerはそれらを再解決しようとせず、単にそのIDを使用します。これは、式を具体化してその結果をマクロ展開で使用すると、そのシンボルが呼び出しサイトに運ばれることを意味します。ええと、すべてのシンボルではありません。たとえば、ローカル変数やプライベート/保護されたものを参照することは不可能ですが、グローバルにアクセス可能な宣言への参照は保持されます。
結論として、マクロが衛生的であるかどうかを確認するには、IDとthisに記号が付いているかどうかを確認します。これは、具象化するか、手作りの木に手動でシンボルを割り当てることで実現できます。
はマクロなのでreify
、その実装を見て、それが何をするのかを理解します。