5

以下宏从http://docs.scala-lang.org/overviews/quasiquotes/usecases.html粘贴:

import reflect.macros.Context
import language.experimental.macros
val universe = reflect.runtime.universe; import universe._
import reflect.runtime.currentMirror
import tools.reflect.ToolBox
val toolbox = currentMirror.mkToolBox()

object debug {
  def apply[T](x: =>T): T = macro impl
  def impl(c: Context)(x: c.Tree) = { import c.universe._
    val q"..$stats" = x
    val loggedStats = stats.flatMap { stat =>
      val msg = "executing " + showCode(stat)
      List(q"println($msg)", stat)
    }
    q"..$loggedStats"
  }
}

它在 Scala 2.11.1 中产生以下错误消息:

Q.scala:9: error: macro implementation reference has wrong shape. required:
macro [<static object>].<method name>[[<type args>]] or
macro [<macro bundle>].<method name>[[<type args>]]
  def apply[T](x: =>T): T = macro impl
                                  ^

我尝试以多种方式更改代码(import reflect.macros.whitebox.Context,,import reflect.macros.blackbox.Context放在scala.每次导入的开头,使参数始终按名称或按值一致,,macro impl[T]摆脱类型参数,,macro debug.impl将) 没有成功。我究竟做错了什么?是进口的东西吗?这些(大部分)来自不同的网页,http://docs.scala-lang.org/overviews/quasiquotes/setup.htmlapplyimpl

该页面的其他两个示例宏都发生了相同的错误:

object Macro {
  def apply(x: Int): Int = macro impl
  def impl(c: Context)(x: c.Expr[Int]): c.Expr[Int] = { import c.universe._
    c.Expr(q"$x + 1")
  }
}

object Macro {
  def apply(x: Int): Int = macro impl
  def impl(c: Context)(x: c.Tree) = { import c.universe._
    q"$x + 1"
  }
}
4

1 回答 1

5

scala Foo.scala将您提供给它的代码包装在一个匿名类中。结果,类似于:

import scala.reflect.macros.Context
import scala.language.experimental.macros

object debug {
  def apply[T](x: T): T = macro impl
  def impl(c: Context)(x: c.Tree): c.Tree = ???
}

转化为:

[[syntax trees at end of                    parser]] // Test.scala
package <empty> {
  object Main extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    def main(args: Array[String]): scala.Unit = {
      final class $anon extends scala.AnyRef {
        def <init>() = {
          super.<init>();
          ()
        };
        import scala.reflect.macros.Context;
        import scala.language.experimental.macros;
        object debug extends scala.AnyRef {
          def <init>() = {
            super.<init>();
            ()
          };
          <macro> def apply[T](x: T): T = impl;
          def impl(c: Context)(x: c.Tree): c.Tree = $qmark$qmark$qmark
        }
      };
      new $anon()
    }
  }
}

但是,必须在静态对象或包中定义宏实现,这就是错误消息试图说明的内容:

/Users/xeno_by/Projects/211x/sandbox/Test.scala:5: error: macro implementation reference has wrong shape. required:
macro [<static object>].<method name>[[<type args>]] or
macro [<macro bundle>].<method name>[[<type args>]]
  def apply[T](x: T): T = macro impl
                                ^
one error found

不幸的是,如果将某些东西放入匿名类中,它就不再是静态的,这意味着scala Foo.scala- 风格的开发与宏不兼容。考虑使用替代方案,例如scalacor sbt

于 2014-05-24T13:53:44.660 回答