Foo
初期値でインスタンス化する特性があるとしますi
val foo = new Foo(6) // class Foo(i: Int)
後で a を呼び出し、secondMethod
それが次に呼び出すmyMacro
foo.secondMethod(7) // def secondMethod(j: Int) = macro myMacro
では、 (6)myMacro
の初期値はどのように求めることができるでしょうか?i
c.prefix
などを使用した通常のコンパイル リフレクションでは成功しませんでしたc.eval(...)
が、代わりに 2 つのプロジェクトの解決策を見つけました。
プロジェクト B:
object CompilationB {
def resultB(x: Int, y: Int) = macro resultB_impl
def resultB_impl(c: Context)(x: c.Expr[Int], y: c.Expr[Int]) =
c.universe.reify(x.splice * y.splice)
}
プロジェクト A (プロジェクト B に依存):
trait Foo {
val i: Int
// Pass through `i` to compilation B:
def apply(y: Int) = CompilationB.resultB(i, y)
}
object CompilationA {
def makeFoo(x: Int): Foo = macro makeFoo_impl
def makeFoo_impl(c: Context)(x: c.Expr[Int]): c.Expr[Foo] =
c.universe.reify(new Foo {val i = x.splice})
}
を作成し、通常のインスタンス化または のようなマクロを使用しFoo
て値を設定できます。2 番目のアプローチでは、最初のコンパイルでコンパイル時に a をカスタマイズし、次に 2 番目のコンパイルで入力への応答をさらにカスタマイズできます (この場合)。何らかの方法で、「メタメタ」機能 (または「空想的」機能 ;-) を取得します。i
makeFoo
Foo
i
通常、イントロスペクトするにはスコープ内に foo が必要ですi
(たとえば、c.eval(...) を使用)。i
しかし、オブジェクト内に値を保存するFoo
ことで、いつでもアクセスでき、Foo
どこでもインスタンス化できます。
object Test extends App {
import CompilationA._
// Normal instantiation
val foo1 = new Foo {val i = 7}
val r1 = foo1(6)
// Macro instantiation
val foo2 = makeFoo(7)
val r2 = foo2(6)
// "Curried" invocation
val r3 = makeFoo(6)(7)
println(s"Result 1 2 3: $r1 $r2 $r3")
assert((r1, r2, r3) ==(42, 42, 42))
}
私の質問
i
このダブル コンパイル ハッカーなしでサンプル マクロ内を見つけることはできますか?