Scala 获取在中定义宏的类的字段成员

Scala 获取在中定义宏的类的字段成员,scala,macros,scala-2.10,scala-macros,Scala,Macros,Scala 2.10,Scala Macros,我试图在trait中定义宏。比如说, 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实现应该能够引用trait宏中的magic字段,安全地键入 我试图通过this(c.enclos

我试图在trait中定义宏。比如说,

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实现应该能够引用trait
宏中的
magic
字段,安全地键入

我试图通过
this(c.enclosuringclass.asModule.moduleClass)
来引用它,但它似乎引用了宏应用程序树,从而生成了一个名为$iw的匿名类。所以在我的理解中,外壳是宏应用的地方,而不是定义宏的地方


无论如何,我都可以这样做吗?

这并不能直接回答问题,但可能还是有帮助的。您可以将实例作为参数传递给宏,要对调用方隐藏它,您可以添加一个相应的方法,将其委托给
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)
  }
}
包装特性:

trait Macro2 extends Macro {
  def doMagic2(x: Int): Int = doMagic(this, x)
}
打电话的人:

val z = new Macro2 {}
println(z.doMagic2(5))

我把它整理好了。我们应该使用c前缀,比如

val self = TermName(c.freshName("self"))

c.Expr[T] {
  q"""
    val $self = ${c.prefix.tree}
    ...
  """
}

并且可以使用自变量来捕获前缀,因此只计算一次。

感谢您的回复,沃尔克。这确实有效。但在我的例子中,参数是一个复杂的DSL类,除非在宏实现内部,否则无法对其进行计算。所以它不适合我的特定用例。