Quasiquotes are a neat notation that lets you manipulate Scala syntax trees (AST) with ease. Quotation syntax is in just another usage of extensible string interpolation.
2. Agenda
● Interpolators, a recap.
● What are quasiqoute?
● Required dependencies and imports.
● ShowRaw and showCode
● Lifting, Unlifting
● Compiling and executing ASTs
● Use case
● References
3. Revisiting Interpolators
➔ It is a mechanism that enable us to
sew/embed/bind WORDS in between a
processed/unprocessed string literal.
➔ We learned about s, raw and f string
interpolators
➔ Now let us uncover what quotation is which is
based on the fundamental of string
interpolators
4. What are Quasiquotes?
Quasiquotes are a neat notation that lets you
manipulate Scala syntax trees (AST) with
ease. Quotation syntax is in just another
usage of extensible string interpolation.
How neat are they?
val tree = q"i am { a quasiquote }"
and we have our AST.
5. What just happened?
The code wrapped inside q”...” is picked up and
an AST is formed from it.
NOTE →
The expression yielded by q”...” is just a tree
which is neither compiled nor executed
6. Justification
What according to you shall be the output for :
● scalac -Xshow-phases
(no compilation has occurred)
● Q”10 / 0”
(no execution has occurred)
8. showRaw and showCode
➔ Understanding the pretty printers with example :
showCode : AST ––> equivalent source code
showRaw : AST ––> organization of the tree
9. Comparing trees
➔ ‘equalsStructure’ is used to determine if two
AST’s are structurally equal or not.
➔ Returns a true if AST are same.
q"I work at knoldus" equalsStructure q”{your
guess}”
10. Unqouting
➔Whenever we unquote an expression of Tree
type in a quasiquote, it will structurally
substitute that tree into the location.
➔Val a = q"class AAA"
➔Val b = q"class BBB"
➔q”$a + $b”
11. Splicing
➔Splicing is a way to unquote a variable number
of elements
➔One possible example can be a method call.
Discuss Example 2
12. Lifting
● Lifting is an extensible way to unquote custom data types
in quasiquotes.
● Int, String, Float (basic types) are all Liftable by default
● Its just
“ T –—> Tree “
val no =5
q”$no + $no”
13. Lifting cont..
● Liftable type is just a trait with a single abstract method that
defines a mapping of given type to tree
trait Liftable[T] {
def apply(value: T): Tree
}
● Whenever there is an implicit value of Liftable[T] available,
one can unquote T (our custom type) in quasiquotes. This
design pattern is known as a type class.
14. Lifting Custom Types
Demonstrating an Example of case class (most widely used
way to implement custom types in Scala) :-
case class Student(name: String, age: Int)
object Student {
implicit val lift = Liftable[Student] { stu =>
q"_root_.Student(${stu.name}, ${stu.age})"
}
}
15. Unlifting
● Unlifting is the reverse operation to lifting.
● It takes a tree and recovers value from it.
● Its just “ Tree –—> Option[T] “ . Why option?
val q"${left: Int} + ${right: Int}" = q"2 + 2"
16. Unlifting Cont..
● Unliftable type is just a trait with a single abstract method
that defines a mapping of given type to tree.
trait Unliftable[T] {
def unapply(tree: Tree): Option[T]
}
● Due to the fact that tree might not be a representation of
our data type, the return type of unapply is Option[T]
rather than just T
17. Unlifting Custom Types
Just add following to previous example
implicit val unliftIt = Unliftable[Student] {
case q"Student(${name: String}, ${age: Int})" =>
Student(name, age)
}
Example 3
18. Compiling and executing the
AST
Toolbox api serves the purpose of compiling the
AST.
Dependencies →
"org.scala-lang" % "scala-compiler" % "2.11.8"
Imports ->
import scala.reflect.runtime.currentMirror
import scala.tools.reflect.ToolBox
19. Compiling
The AST can be compiled using the compile
method of Toolbox with following signature :
abstract def compile(tree : U.Tree): () Any⇒
It throws an compilation error if compilation fails.
20. Executing
The AST can be compiled and executed using the
eval method of Toolbox with following signature :
abstract def eval(tree : U.Tree): Any
It throws an compilation error if compilation fails
and runtime error if execution fails.
21. Use cases
● Easy AST manipulation
● Offline code generation(AST to corrosponding
code using showCode method)
● Just in time compilation using Toolbox api