我有下一个代码:
object TestMacro {
def test[A](vval: List[A]) = macro testImpl[A]
def testImpltestImpl[A: c.WeakTypeTag](c: Context)(vval: c.Expr[List[A]]) = {
import c.universe._
println(vval) // => Expr[Nothing](immutable.this.List.apply[Int](1, 2, 3))
reify{}
}
}
示例:
test(List(1,2,3))
如何从List[Int]
获取真实类型Expr
并获取宏中具有(1,2,3)
值的List实例?
答案 0 :(得分:2)
您可以使用方法showRaw
获取Tree
结构,如下所示:
import reflect.runtime.universe._
showRaw{ reify{ List(1, 2, 3) } }
// Expr(Apply(Select(Ident(scala.collection.immutable.List), newTermName("apply")), List(Literal(Constant(1)), Literal(Constant(2)), Literal(Constant(3)))))
reify
返回Expr
。
缩进的结果:
Expr(
Apply(
Select(
Ident(scala.collection.immutable.List),
newTermName("apply")
),
List(
Literal(Constant(1)),
Literal(Constant(2)),
Literal(Constant(3))
)
)
)
所以你可以解构这棵树:
val vval = reify{ List(1, 2, 3) }
val l =
vval.tree match {
case Apply(_, l) => l
}
// List[reflect.runtime.universe.Tree] = List(1, 2, 3)
val ints =
l map {
case Literal(Constant(i: Int)) => i
}
// List[Int] = List(1, 2, 3)
请注意,只有当您的方法test
被调用为test(List(1, 2, 3))
时,它才会起作用。它将在val l = List(1, 2, 3); test(l)
失败。它甚至会在test(List(1+1))
上失败。
此类参数提取的唯一有用应用是基于宏的字符串插值like this。