【问题标题】:Scala Quasiquote LiftingScala Quasiquote 提升
【发布时间】:2015-05-12 05:56:17
【问题描述】:

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)

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

【问题讨论】:

    标签: scala scala-quasiquotes


    【解决方案1】:

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

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

    引用文档:

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

    在这里,可变数量的元素将是我们想要取消引用的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))
    

    再一次,文档说得最好,真的:

    未引用的点附近的点表示扁平化程度,也称为拼接等级。 ..$ 期望参数是 Iterable[Tree]...$ 期望 Iterable[Iterable[Tree]]

    所以 lifting 允许我们将 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)
    

    【讨论】:

    • 谢谢,但我只想说,给一个表面上用前缀 un- 替换的机制命名是多么愚蠢。
    • 这并不愚蠢。符号被解析为它们所指的内容,如果val x = 5 然后稍后x 将是5。引用给出了一个符号,'x 是符号 x 本身。稍后您可以 unqoute 'x 并将其放入将在该上下文中引用某些内容的代码中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2013-07-31
    • 1970-01-01
    • 2023-03-29
    相关资源
    最近更新 更多