Scala Quasiquote提升

时间:2015-05-10 19:46:39

标签: scala scala-quasiquotes

Quasiquotes的Scala文档在解释Lifting

时提到了这一点
  

还可以结合提升和非引用拼接:

 scala> val ints = List(1, 2, 3)
 scala> val f123 = q"f(..$ints)"
 f123: universe.Tree = f(1, 2, 3)

 scala> val intss = List(List(1, 2, 3), List(4, 5), List(6))
 scala> val f123456 = q"f(...$intss)"
 f123456: universe.Tree = f(1, 2, 3)(4, 5)(6)
 

具体是代码示例中提升与非引用拼接的实现?

1 个答案:

答案 0 :(得分:5)

这两个例子都在同一时间发生。

Unquoting 是将Tree替换为另一个Tree的结构(如插值)的过程。在此示例中,ints并非Tree,但存在Liftable[List[T]],允许我们将List[T]取消引用到Tree,好像它是Tree(即Liftable告诉编译器如何将文字List[Int]转换为Tree,以便它可以被替换。)

引用文档:

  

取消引用拼接是一种取消引用可变数量元素的方法。

这里,可变数量的元素将是我们想要取消引用的List中的元素。如果我们执行了q"f($ints)",那么我们只需将ints取消引用为f的单个参数。但也许我们想要将重复的参数应用到f。为此,我们使用 unquote拼接

q"f(..$ints) // Using `..` means we get f(1, 2, 3) instead of f(List(1, 2, 3))

同样,文档说得最好,真的:

  

靠近无条件的点注释扁平程度,也称为拼接等级。 ..$期望参数为Iterable[Tree]...$期望为Iterable[Iterable[Tree]]

所以提升允许我们将List[T]取消引用到树f(x)中,就像它是Iterable[Tree]一样,并且取消引用拼接允许我们将List[T]包含的可变数量的元素取消引用为f的多个参数。

以下是不同的相关组合:

val listTree = q"scala.collection.immutable.List(1, 2, 3)"
val treeList = List(q"1", q"2", q"3")
val literalList = List(1, 2, 3)

scala> q"f($listTree)" // plain unquoting from another Tree
res6: reflect.runtime.universe.Tree = f(scala.collection.immutable.List(1, 2, 3))

scala> q"f($literalList)" // unquoting from lifting
res7: reflect.runtime.universe.Tree = f(scala.collection.immutable.List(1, 2, 3))

scala> q"f(..$treeList)" // plain unquote splicing
res8: reflect.runtime.universe.Tree = f(1, 2, 3)

scala> q"f(..$literalList)" // unquote splicing and lifting
res9: reflect.runtime.universe.Tree = f(1, 2, 3)