Scala Quasiquote Lifting

Документация Scala для Quasiquotes упоминает это при объяснении 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 ответ

Решение

Оба происходят одновременно в обоих примерах.

Отмена цитирования - это процесс замены Tree где-то в структуре другого Tree (как интерполяция). В этом примере ints не совсем Tree, но существует Liftable[List[T]] что позволяет нам убрать цитату List[T] в Tree как будто это Tree (т.е. Liftable говорит компилятору, как преобразовать литерал List[Int] здесь в Tree так что это можно заменить).

Цитировать документацию:

Сплайсирование без кавычек - это способ удаления кавычек с переменным количеством элементов.

Здесь переменное число элементов будет элементами в List мы хотим отменить цитату. Если бы мы сделали q"f($ints)" тогда мы просто откажемся ints в качестве единственного аргумента f, Но, возможно, мы хотим применить повторные параметры к f вместо. Для этого мы используем сплайсинг без кавычек.

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

Снова, документация говорит это лучше всего, действительно:

Точки, близкие к unquotee, обозначают степень уплощения и также называются рангом сплайсинга. ..$ ожидает, что аргумент будет 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)
Другие вопросы по тегам