4

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)

代码示例中提升与取消引用拼接的具体实现在哪里?

4

1 回答 1

5

在这两个示例中,两者都同时发生。

取消引用Tree是将某处替换为另一个结构的过程Tree(如插值)。在此示例中,intsis 不完全是 a Tree,但存在 aLiftable[List[T]]允许我们将 a 取消引用List[T]为 a Tree,就好像它是 a 一样Tree(即Liftable告诉编译器如何将List[Int]此处的文字转换为 aTree以便可以替换它) .

引用文档:

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

在这里,可变数量的元素将是List我们想要取消引用的元素。如果我们这样做了q"f($ints)",那么我们将简单地取消引用ints作为 的单个参数f。但也许我们想改为应用重复的参数f。为此,我们使用unquote splicing

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

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

unquotee 附近的点表示扁平化程度,也称为拼接等级。..$期望参数是一个Iterable[Tree]并且...$期望Iterable[Iterable[Tree]]

因此,提升允许我们将 a取消引用List[T]到树f(x)中,就好像它是 an 一样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)
于 2015-05-10T21:19:08.497 回答