4

Quasiquotes の Scala ドキュメントでは、Liftingを説明するときにこれについて言及しています。

リフティングと unquote スプライシングを組み合わせることもできます。

 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)

コード例で、リフティングと unquote スプライシングの実装は具体的にどこにありますか?

4

1 に答える 1

5

両方の例で、両方が同時に起こっています。

引用符Treeを外すことは、どこかを別の構造に置き換えるプロセスですTree(補間のように)。この例でintsは、 は正確には a ではありませんが、あたかもa であるかのように、 aを aにクォート解除できるTreea が存在します(つまり、は、ここのリテラルを aに変換して置換できるようにする方法をコンパイラに指示します)。 .Liftable[List[T]]List[T]TreeTreeLiftableList[Int]Tree

ドキュメントを引用するには:

アンクォートスプライシングは、可変数の要素をアンクォートする方法です。

Listここで、可変数の要素は、引用符を外したいの要素になります。を実行した場合、 の単一の引数としてq"f($ints)"引用符を外すだけです。しかし、代わりに繰り返しパラメータを適用したいかもしれません。そのためにunquote splicingを使用します。intsff

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)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 に答える