我有一个序列val xs: Seq[T]
和一个函数f(xs: T*)
。
我想编写一个在编译时将f(xs: _*)
扩展为f(x1, x2, ... xn)
的宏,但我在成功eval
Expr
时遇到了很多麻烦在宏观中。我尝试过几种不同的方法。 scala.tools.reflect.ToolBox
抱怨c.universe
与运行时Universe不匹配。 c.eval(...)
抱怨树已被类型检查,并且运行c.untypecheck
只会给我带来更多类型错误。
答案 0 :(得分:1)
"序列arg"定义http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#function-applications
scala> import reflect.macros.blackbox.Context
import reflect.macros.blackbox.Context
scala> def f[A: c.WeakTypeTag](c: Context)(arg: c.Expr[A]*) = { import c.universe._ ; println(arg.map(x => showRaw(x.tree))) ; q"${arg.size}" }
f: [A](c: scala.reflect.macros.blackbox.Context)(arg: c.Expr[A]*)(implicit evidence$1: c.WeakTypeTag[A])c.universe.Tree
scala> def g[A](arg: A*): Int = macro f[A]
defined term macro g: [A](arg: A*)Int
scala> val xs = List(1,2,3)
xs: List[Int] = List(1, 2, 3)
scala> g(xs, 42)
List(Select(Select(Select(Select(Ident($line16), $line16.$read), $line16.$read.$iw), $line16.$read.$iw.$iw), TermName("xs")), Literal(Constant(42)))
res0: Int = 2
scala> g(42, xs: _*)
List(Literal(Constant(42)), Typed(Select(Select(Select(Select(Ident($line16), $line16.$read), $line16.$read.$iw), $line16.$read.$iw.$iw), TermName("xs")), Ident(typeNames.WILDCARD_STAR)))
res1: Int = 2
scala> g(1,2,3)
List(Literal(Constant(1)), Literal(Constant(2)), Literal(Constant(3)))
res2: Int = 3
运行时代码见:
scala> def count[A](as: A*): Int = as.size
count: [A](as: A*)Int
scala> count(xs)
res4: Int = 1
scala> count(xs: _*)
res5: Int = 3