【问题标题】:Expand scala splat at compile time using macros and eval在编译时使用宏和 eval 展开 scala splat
【发布时间】:2016-09-30 01:39:37
【问题描述】:

我有一个序列val xs: Seq[T] 和一个函数f(xs: T*)

我想编写一个在编译时将f(xs: _*) 扩展为f(x1, x2, ... xn) 的宏,但是我在宏中成功evaling Expr 时遇到了很多麻烦。我尝试了几种不同的方法。 scala.tools.reflect.ToolBox 抱怨 c.universe 与运行时宇宙不匹配。 c.eval(...) 抱怨树已经过类型检查,运行 c.untypecheck 只会给我更多类型错误。

【问题讨论】:

  • 您是否知道宏接收树,并且重复的参数已经作为 Seq 提供?在 gitter 澄清这些问题时,您可能会有更好的运气。
  • 如果在编译时将重复参数作为 Seq 提供,为什么 f(xs) 无法进行类型检查而 f(xs: _*) 成功? _* 到底在做什么?
  • 无论如何,如果这是真的,问题就变成了评估 Seq 并将其扩展为参数列表。

标签: scala macros scala-macros


【解决方案1】:

“序列参数”定义http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#function-applications

你的宏看到https://github.com/scala/scala/blob/v2.12.0-RC1/src/reflect/scala/reflect/internal/TreeInfo.scala#L578

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-15
    • 2017-12-12
    • 2015-10-23
    相关资源
    最近更新 更多