"Ссылка на реализацию макроса имеет неправильную форму" в примерах документации Scala
Следующий макрос вставлен из 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
, положив apply
после impl
и многое другое) безуспешно. Что я делаю неправильно? Это что-то в импорте? Они приходят (в основном) с другой веб-страницы: http://docs.scala-lang.org/overviews/quasiquotes/setup.html.
Та же ошибка возникает в обоих других примерных макросах с этой страницы:
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"
}
}
1 ответ
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
разработка стиля несовместима с макросами. Рассмотрите возможность использования альтернатив, например, scalac
или же sbt
,