Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Introduction to Quasiquotes

2,296 views

Published on

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.

Published in: Software
  • Be the first to comment

Introduction to Quasiquotes

  1. 1. Introduction to QUASIQUOTES By :- SAHIL SAWHNEY Software Consultant KNOLDUS SOFTWARE LLP By :- SAHIL SAWHNEY Software Consultant KNOLDUS SOFTWARE LLP
  2. 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. 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. 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. 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. 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)
  7. 7. Dependencies and imports. ➔ Dependencies : "org.scala-lang" % "scala-reflect" % "2.11.8" ➔ Imports : import scala.reflect.runtime.universe import universe._
  8. 8. showRaw and showCode ➔ Understanding the pretty printers with example : showCode : AST ––> equivalent source code showRaw : AST ––> organization of the tree
  9. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 21. Use cases ● Easy AST manipulation ● Offline code generation(AST to corrosponding code using showCode method) ● Just in time compilation using Toolbox api
  22. 22. References http://www.scala-lang.org/api/2.12.0-M4/scala-compiler http://docs.scala-lang.org/overviews/quasiquotes/intro https://www.youtube.com/watch?v=_c6SMsZNxms http://www.scala-lang.org/api/2.12.0-M4/scala-compiler http://docs.scala-lang.org/overviews/quasiquotes/intro https://www.youtube.com/watch?v=_c6SMsZNxms
  23. 23. Thank You !!!

×