#scala #pattern-matching #abstract-syntax-tree #scala-macros
#scala #сопоставление с образцом #абстрактное синтаксическое дерево #scala-макросы
Вопрос:
Рассмотрим следующий фрагмент
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(_)
с одинаково неудовлетворительными результатами).
Почему? И что мне нужно сопоставить вместо этого?
Комментарии:
1. Вы пробовали сопоставлять
v.tree
вместо этого?2. @Actorclavilis Такая глупая вещь. -.- Спасибо. Хотите уточнить, чтобы я мог принять это как ответ?
Ответ №1:
Ваш implDebug
метод принимает a c.Expr[Any]
, который является оболочкой для a c.Tree
. Literal(Constant(...))
является правильным средством сопоставления для значения литерального дерева, но поскольку вы хотите, чтобы оно соответствовало дереву, вам следует использовать v.tree match {...}
вместо этого.