在编译时使用宏和 eval 扩展 scala splat
Expand scala splat at compile time using macros and eval
我有一个序列 val xs: Seq[T]
和一个函数 f(xs: T*)
。
我想编写一个在编译时将 f(xs: _*)
扩展到 f(x1, x2, ... xn)
的宏,但是我在成功 eval
ing [=15] 时遇到了很多麻烦=] 在宏中。我尝试了几种不同的方法。 scala.tools.reflect.ToolBox
抱怨 c.universe
与运行时宇宙不匹配。 c.eval(...)
抱怨树已经过类型检查,运行 c.untypecheck
只是给我更多的类型错误。
"Sequence 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: 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
我有一个序列 val xs: Seq[T]
和一个函数 f(xs: T*)
。
我想编写一个在编译时将 f(xs: _*)
扩展到 f(x1, x2, ... xn)
的宏,但是我在成功 eval
ing [=15] 时遇到了很多麻烦=] 在宏中。我尝试了几种不同的方法。 scala.tools.reflect.ToolBox
抱怨 c.universe
与运行时宇宙不匹配。 c.eval(...)
抱怨树已经过类型检查,运行 c.untypecheck
只是给我更多的类型错误。
"Sequence 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: 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