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)