假设我有一个lambda,我使用reify将其转换为包裹在树周围的Expr。例如
val expr = reify{x: Int => 3*(4+x)}
我可以对特定的x进行评估,如下所示
val toolbox = currentMirror.mkToolBox()
val fun = toolbox.eval(expr.tree).asInstanceOf[Int => Int]
println(fun(10))
我的目标是打印整个树,用每个子表达式的值注释。如何确定所有子表达式及其值?例如,确定当x为10时,则存在子表达式
(4+x)
计算结果为14.Traverser类允许我访问树中的每个节点,但我无法弄清楚如何评估每个节点的子树。
例如,使用以下
class TestTraverser extends Traverser {
override def traverse(tree: Tree): Unit = {
val toolbox = currentMirror.mkToolBox()
tree match {
case app @ Apply(fun, args) =>
val f = toolbox.eval(app.fun)
case _ =>
}
super.traverse(tree)
}
}
致电
new TestTraverser().traverse(expr.tree)
导致此异常
scala.tools.reflect.ToolBoxError: reflective compilation has failed:
ambiguous reference to overloaded definition,
both method * in class Int of type (x: Char)Int
and method * in class Int of type (x: Byte)Int
match expected type Any
答案 0 :(得分:0)
自己解决了这个问题。为了在子树上调用toolbox.eval
,您需要使用指示它是名为Int
x
的函数的信息重新包装子树。以下是有效的Traverser
示例。
class WorkingTraverser extends Traverser {
val toolbox = currentMirror.mkToolBox()
override def traverse(tree: Tree): Unit = {
tree match {
case app @ Apply(fun, args) =>
val newfun = Function(List(ValDef(Modifiers(PARAM), TermName("x"), Ident(TypeName("Int")), EmptyTree)), Apply(app.fun, app.args))
val f = toolbox.eval(newfun)
val f2 = f.asInstanceOf[Int => Int]
println(app.fun + "(" + app.args + ")" + " evaluates to " + f2(10))
super.traverse(fun)
super.traverseTrees(args)
case _ => super.traverse(tree)
}
}
}