EXPERIMENTAL
Eugene Burmako 著
Eugene Yokota 訳
マクロバンドル (macro bundle) は、Scala 2.11.x および Scala 2.12.x 系列に含まれる機能だ。マクロバンドルは Scala 2.10.x では実装されていない。Scala 2.10.x 向けのマクロパラダイスでも、これは実装されていない。
マクロバンドル
Scala 2.10.x においてマクロ実装は関数として表されている。コンパイラがマクロ定義の適用を見つけると、マクロ実装を呼び出すという単純なものだ。しかし、実際に使ってみると以下の理由によりただの関数では不十分なことがあることが分かった:
- 関数に制限されることで複雑なマクロのモジュール化がしづらくなる。マクロのロジックがマクロ実装外のヘルパートレイトに集中していて、マクロ実装がヘルパーをインスタンス化するだけのラッパーになってしまっているのは典型的な例だ。
- さらに、マクロのパラメータがマクロのコンテキストにパス依存であるため、ヘルパーと実装をつなぐのに特殊なおまじないを必要とする。
マクロバンドルは、マクロ実装を
c: scala.reflect.macros.blackbox.Context
か
c: scala.reflect.macros.whitebox.Context
をコンストラクタのパラメータとして受け取るクラス内で実装することで、コンテキストをマクロ実装側のシグネチャで宣言しなくても済むようになり、モジュール化を簡単にする。
import scala.reflect.macros.blackbox.Context
class Impl(val c: Context) {
def mono = c.literalUnit
def poly[T: c.WeakTypeTag] = c.literal(c.weakTypeOf[T].toString)
}
object Macros {
def mono = macro Impl.mono
def poly[T] = macro Impl.poly[T]
}
blackbox vs whitebox
マクロバンドルは、blackbox と whitebox
の両方のマクロの実装に使うことができる。マクロバンドルのコンストラクタのパラメータに
scala.reflect.macros.blackbox.Context
の型を渡せば blackbox マクロになって、
scala.reflect.macros.whitebox.Context
ならば whitebox マクロになる。