假设我有一个Foo
用初始值实例化的特征i
val foo = new Foo(6) // class Foo(i: Int)
我后来打电话给一个secondMethod
反过来打电话myMacro
foo.secondMethod(7) // def secondMethod(j: Int) = macro myMacro
那么,怎样才能找到(6)myMacro
的初值呢?i
我没有成功使用 等进行正常编译反射c.prefix
,c.eval(...)
而是找到了一个 2-project 解决方案:
项目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
并设置值。第二种方法允许我们在第一次编译时在编译时自定义一个,然后在第二次编译中进一步自定义它对输入的响应(在这种情况下)!在某种程度上,我们获得了“元元”能力(或“超形上学”能力;-)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
如果没有这个双重编译黑客,我可以在我的示例宏中找到吗?