Tra*_*own 27 macros scala scala-macros scala-quasiquotes
这个问题与我之前的问题的动机相似(虽然它是关于我在不同背景下遇到的问题).
在没有quasiquotes的情况下,我可以非常轻松地在函数文字上进行模式匹配:
import scala.reflect.macros.Context
import scala.language.experimental.macros
object QQExample {
def funcDemo(f: Int => String) = macro funcDemo_impl
def funcDemo_impl(c: Context)(f: c.Expr[Int => String]) = {
import c.universe._
f.tree match {
case Function(ps, body) => List(ps, body) foreach println
case _ => c.abort(
c.enclosingPosition,
"Must provide a function literal."
)
}
c.literalUnit
}
}
Run Code Online (Sandbox Code Playgroud)
其工作方式如下:
scala> QQExample.funcDemo((a: Int) => a.toString)
List(val a: Int = _)
a.toString()
Run Code Online (Sandbox Code Playgroud)
现在假设我想使用quasiquotes更灵活地进行相同类型的匹配.以下内容也将匹配该功能,并打印出我们期望的内容.
case q"($x: $t) => $body" => List(x, t, body) foreach println
Run Code Online (Sandbox Code Playgroud)
但是如果我想在模式中指定类型,则它不匹配:
case q"($x: Int) => $body" => List(x, body) foreach println
Run Code Online (Sandbox Code Playgroud)
并且以下都不编译:
case q"$p => $body" => List(p, body) foreach println
case q"($p) => $body" => List(p, body) foreach println
case q"..$ps => $body" => List(ps, body) foreach println
case q"(..$ps) => $body" => List(ps, body) foreach println
Run Code Online (Sandbox Code Playgroud)
当使用quasiquotes匹配函数文本时,是否可以指定参数的类型,或者匹配未知数量的参数?
使用最新的2.10天堂插件和香草2.11你可以这样做:
val q"(..$args) => $body" = f.tree
Run Code Online (Sandbox Code Playgroud)
我刚用天堂示例项目测试了以下内容Macros.scala:
import language.experimental.macros
import scala.reflect.macros.Context
object Macro {
def apply(f: Any): Any = macro impl
def impl(c: Context)(f: c.Expr[Any]) = { import c.universe._
val q"(..$args) => $body" = f.tree
println(s"args = $args, body = $body")
c.Expr(q"()")
}
}
Run Code Online (Sandbox Code Playgroud)
而且Test.scala:
object Test extends App {
Macro((x: Int) => x + 1)
}
Run Code Online (Sandbox Code Playgroud)
您可以在准引导的相应章节中阅读更多关于使用quasiquotes处理函数树的内容.