带准引号的模式匹配树的稳健性
Robustness of pattern matching Trees with quasiquotes
我有一个宏,该宏的一部分包括用其他方法替换对特定方法的每次调用。为此,我使用 Transformer
并尝试将每个进入 transform
方法的 Tree
与准引用相匹配。当我像下面这样写时,它似乎有效。
package mypackage
object myobject {
implicit def mymethod[T](t: Option[T]): T = ???
}
object Macros {
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
def myMacro(c: Context)(expr: c.Tree): c.Tree = {
import c.universe._
val transformer = new Transformer {
private def doSomething(value: c.Tree): TermName = {
???
}
override def transform(tree: c.Tree) = tree match {
case q"mypackage.myobject.mymethod[..$_]($value)" =>
val result = doSomething(value)
q"$result"
case _ => super.transform(tree)
}
}
val transformed = transformer.transform(expr)
???
}
}
但我认为您应该始终在宏中使用完全限定的名称,否则您可能会遇到麻烦。所以我把它写成 q"_root_.mypackage.myobject.mymethod[..$_]($value)"
,但后来它不再匹配并且对 mymethod
的调用不再被替换。
我还查看了 the scala docs 中关于取消引用符号的建议,但我也无法使它起作用。
所以我的问题是:此代码(带有 q"mypackage.myobject.mymethod[..$_]($value)"
)是否会始终替换对 mymethod
的所有调用并且从不替换任何其他方法调用?如果没有,我怎样才能让它更健壮?
scala.reflect宏是不卫生的,所以,理论上,q"mypackage.myobject.mymethod[..$_]($value)"
可以被其他人匹配。
我建议将该方法与 q"..$mods def $name[..$tparams](...$paramss): $tpeopt = $expr"
匹配(假设这是定义,而不是声明)。您可以在 name
.
上添加检查
另一种解决方法是用注解标记方法,在宏阶段去掉。
我有一个宏,该宏的一部分包括用其他方法替换对特定方法的每次调用。为此,我使用 Transformer
并尝试将每个进入 transform
方法的 Tree
与准引用相匹配。当我像下面这样写时,它似乎有效。
package mypackage
object myobject {
implicit def mymethod[T](t: Option[T]): T = ???
}
object Macros {
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
def myMacro(c: Context)(expr: c.Tree): c.Tree = {
import c.universe._
val transformer = new Transformer {
private def doSomething(value: c.Tree): TermName = {
???
}
override def transform(tree: c.Tree) = tree match {
case q"mypackage.myobject.mymethod[..$_]($value)" =>
val result = doSomething(value)
q"$result"
case _ => super.transform(tree)
}
}
val transformed = transformer.transform(expr)
???
}
}
但我认为您应该始终在宏中使用完全限定的名称,否则您可能会遇到麻烦。所以我把它写成 q"_root_.mypackage.myobject.mymethod[..$_]($value)"
,但后来它不再匹配并且对 mymethod
的调用不再被替换。
我还查看了 the scala docs 中关于取消引用符号的建议,但我也无法使它起作用。
所以我的问题是:此代码(带有 q"mypackage.myobject.mymethod[..$_]($value)"
)是否会始终替换对 mymethod
的所有调用并且从不替换任何其他方法调用?如果没有,我怎样才能让它更健壮?
scala.reflect宏是不卫生的,所以,理论上,q"mypackage.myobject.mymethod[..$_]($value)"
可以被其他人匹配。
我建议将该方法与 q"..$mods def $name[..$tparams](...$paramss): $tpeopt = $expr"
匹配(假设这是定义,而不是声明)。您可以在 name
.
另一种解决方法是用注解标记方法,在宏阶段去掉。