考虑以下代码段
object Main {
def main(args:Array[String]): Unit ={
import Debugger.debug
debug("Hello World")
val x = 0
debug(x)
debug(1)
}
}
我想要打印
Hello World
x = 0
1
通过使用宏:
import scala.language.experimental.macros
import scala.reflect.macros._
object Debugger {
val doDebug = true
def debug(v : Any) :Unit = macro implDebug
def implDebug(c:blackbox.Context)(v:c.Expr[Any]): c.Expr[Unit] ={
import c.universe._
if(doDebug) {
v match {
case Literal(Constant(_)) => reify{println(v.splice)}
case _ =>
println(v.tree)
println(v.tree.getClass.getName)
val rep = show(v.tree)
val repTree = Literal(Constant(rep))
val repExpr = c.Expr[String](repTree)
reify{
println(repExpr.splice + " = " + v.splice)
}
}
}
else reify{}
}
}
输出(编译+运行):
[sbt compile bla bla]
"Hello World"
scala.reflect.internal.Trees$Literal
x
scala.reflect.internal.Trees$Ident
1
scala.reflect.internal.Trees$Literal
[info] Running Main
"Hello World" = Hello World
x = 0
1 = 1
所以......显然,“Hello World”是一个文字但是与文字模式不匹配(也尝试了case Literal(_)
同样不满意的结果)。
为什么呢?我需要匹配什么呢?
答案 0 :(得分:2)
您的implDebug
方法正在接受c.Expr[Any]
,这是c.Tree
的包装。 Literal(Constant(...))
是文字树值的正确匹配器,但由于您希望在树上进行匹配,因此应使用v.tree match {...}
代替。