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)
具体是代码示例中提升与非引用拼接的实现?
答案 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)