macro in scala

17
Macro in Scala Naoki Takezoe @takezoen BizReach, Inc 1 Oct. 2016 #渋谷java 17th

Upload: takezoe

Post on 09-Jan-2017

3.109 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Macro in Scala

Macro in ScalaNaoki Takezoe

@takezoenBizReach, Inc

1 Oct. 2016 #渋谷java 17th

Page 2: Macro in Scala

What's Macro?

Page 3: Macro in Scala

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

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

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

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

Use cases

Page 8: Macro in Scala

Use cases

● Validation● Type generation● DSL● Optimization

without runtime overhead

Page 9: Macro in Scala

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

Macro in Scala

Page 11: Macro in Scala

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

How to construct AST?

● AST model● reify● Quasiquotes

Page 13: Macro in Scala

AST model

def compileTimeImpl(c: Context)() = { Literal(Constant(new java.util.Date().toString))}

Page 14: Macro in Scala

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

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

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

Let's learn Macro!