O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

Introduction to Quasiquotes

2.258 visualizações

Publicada em

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.

Publicada em: Software
  • Seja o primeiro a comentar

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 !!!

×