macro in scala
TRANSCRIPT
![Page 1: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/1.jpg)
Macro in ScalaNaoki Takezoe
@takezoenBizReach, Inc
1 Oct. 2016 #渋谷java 17th
![Page 2: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/2.jpg)
What's Macro?
![Page 3: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/3.jpg)
C
Expand special directive in source code before compilation by pre-processor
#define square(x) ((x) * (x))printf("i * i = %d\n", i, square(i));
#define DEBUG#ifdef DEBUG printf("debug: i = %d\n", i)#endif
![Page 4: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/4.jpg)
Lisp (also Scala or Rust)
Generate AST in compile-time
(defmacro when (test &body body) `(if ,test (progn ,@body)))
(progn (when (= 1 1) (print "Hello,") (print "World!!")))
(progn (if (= 1 1) (progn (print "Hello,") (print "World!!"))))
Expand by Macro
![Page 5: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/5.jpg)
Example in Scala
def assert(cond: Boolean, msg: String): Unit = macro assertImpl
def assertImpl(c: Context) (cond: c.Expr[Boolean], msg: c.Expr[String]) = { import c.universe._ q"if(!$cond){ throw new AssertionError($msg) }"}
![Page 6: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/6.jpg)
Example in Scala
assert(i == 1, "i does not 1")
if(i == 1){ throw new AssertionError("i does not 1")}
Expand by Macro
Note: Macro have to be compiled before main compilation
![Page 7: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/7.jpg)
Use cases
![Page 8: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/8.jpg)
Use cases
● Validation● Type generation● DSL● Optimization
without runtime overhead
![Page 9: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/9.jpg)
Quill
● Database access library for Scala● Do in compile-time by macro
○ Translate typesafe DSL to SQL○ SQL validation against real database
val q = quote { query[Person].filter(p => p.age > 18)}
// SELECT p.id, p.name, p.age FROM Person p WHERE p.age > 18
http://getquill.io/
![Page 10: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/10.jpg)
Macro in Scala
![Page 11: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/11.jpg)
Macro type
● def macro○ callable as same as normal function
● Macro annotation○ triggered by annotation○ requires Macro Paradise plug-in
@main object Test { println("hello world")}
object Test { def main(args: Array[String]): Unit = { println("hello world") }}
Expand by Macro annotation
![Page 12: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/12.jpg)
How to construct AST?
● AST model● reify● Quasiquotes
![Page 13: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/13.jpg)
AST model
def compileTimeImpl(c: Context)() = { Literal(Constant(new java.util.Date().toString))}
![Page 14: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/14.jpg)
reify
def assertImpl(c: Context) (cond: c.Expr[Boolean], msg: c.Expr[String]) = { import c.universe._ reify(if(!cond.splice){ throw new AssertionError(msg.splice) })}
![Page 15: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/15.jpg)
Quasiquotes
def assertImpl(c: Context) (cond: c.Expr[Boolean], msg: c.Expr[String]) = { import c.universe._ q"if(!$cond){ throw new AssertionError($msg) }"}
![Page 16: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/16.jpg)
Future: scala.mata
● Metaprogramming toolkit for Scala● Replace scala.reflect
○ More simple and safe● Scala Macro will move to scala.meta based
○ Only Macro annotation is available by Macro Paradise plug-in currently
![Page 17: Macro in Scala](https://reader036.vdocuments.pub/reader036/viewer/2022092623/5872dae91a28ab74188b70bb/html5/thumbnails/17.jpg)
Let's learn Macro!