我正在尝试在特征中定义一个宏。例如,
trait Macro {
val magic: Int = 1001
def doMagic(x: Int): Int = macro Impl.doMagic
}
object Impl {
def doMagic(c: Context)(x: c.Expr[Int]): c.Expr[Int] = ???
}
我在这里要做的是,doMagic实现应该能够引用特征magic
中的字段Macro
,安全地输入。
我试图通过This(c.enclosingClass.asModule.moduleClass)
来引用它,但它似乎引用了宏应用程序的树,这导致了一个名为$ iw的匿名类。所以在我的理解中,Enclosures是应用宏的地方,而不是它被定义的地方。
无论如何我能做到吗?
答案 0 :(得分:1)
这不直接回答问题,但也许它有所帮助。您可以将实例作为参数传递给宏,并将其隐藏在调用者中,您可以添加委托给doMagic
的相应方法,如下所示:
trait Macro {
val magic: Int = 1001
def doMagic(m: Macro, x: Int): Int = macro Impl.doMagic
}
object Impl {
def doMagic(context: Context)(m: context.Expr[Macro], x: context.Expr[Int]): context.Expr[Int] = {
import context.universe._
reify(m.splice.magic + x.splice)
}
}
wrapper-trait:
trait Macro2 extends Macro {
def doMagic2(x: Int): Int = doMagic(this, x)
}
和来电者:
val z = new Macro2 {}
println(z.doMagic2(5))
答案 1 :(得分:0)
我整理出来了。我们应该使用c.prefix,比如
val self = TermName(c.freshName("self"))
c.Expr[T] {
q"""
val $self = ${c.prefix.tree}
...
"""
}
并且可以使用自变量来捕获前缀,因此它只被评估一次。