scala macros

33
SCALA MACROS Adam Warski, JavaZone 2013 @adamwarski

Upload: adam-warski

Post on 30-Oct-2014

1.399 views

Category:

Technology


1 download

DESCRIPTION

JavaZone 2013 Scala Macros

TRANSCRIPT

Page 1: Scala Macros

SCALA MACROS

Adam Warski, JavaZone 2013 @adamwarski

Page 2: Scala Macros

@adamwarski

ATTEND THIS TALK IF … … you are curious what a macro is … you are wondering how to write a macro in Scala

… you have not yet decided if you love or hate macros

… you’d like to know if they are used anywhere

Page 3: Scala Macros

@adamwarski

WHAT IS A MACRO?

•  Macro (large): expands into something larger

•  Function: code => code!•  Invoked at build/compile-time

Page 4: Scala Macros

@adamwarski

SCALA MACROS •  Written in Scala •  Have access to and can manipulate the AST •  Use compiler/reflection APIs

•  Type-safe

Page 5: Scala Macros

@adamwarski

MACROS IN OTHER LANGUAGES C/C++ – preprocessor

•  #define BUFFER_SIZE 1024 •  #define min(X, Y) ((X) < (Y) ? (X) : (Y))

Lisp/Clojure, Racket (Scheme)

•  code is data (list) •  quoting •  “Since macros are so much harder to use than functions, a

good rule of thumb is: don't use defmacro if defun will work fine” from http://www.apl.jhu.edu/~hall/Lisp-Notes/Macros.html

Page 6: Scala Macros

@adamwarski

MOTIVATION TO ADD MACROS TO SCALA

(it’s not a lean language already!) ü  Remove boilerplate

ü  Replace run-time reflection

ü  Generate type-checked code

ü  Deep embedding of DSLs

ü  Type-check external DSLs ü  Simplify compiler in the long run

Page 7: Scala Macros

@adamwarski

REACTIONS TO MACROS Mixed ;)

Page 8: Scala Macros

@adamwarski

PLAN FOR THE NEXT 50 MINUTES

1.  How to write a simple macro 2.  Where macros are used now?

3.  Upcoming new types of macros

Page 9: Scala Macros

@adamwarski

ABOUT ME During the day: coding @ SoftwareMill SoftwareMill: a great software house! Afternoon: playgrounds, Duplo, etc.

Evening: blogging, open-source •  Original author of Hibernate Envers •  ElasticMQ, Veripacks, MacWire

http://www.warski.org

Page 10: Scala Macros

@adamwarski

“DEF” MACROS

•  Available since Scala 2.10 (Jan 2013)

•  Only one type of many possible macro types

•  Experimental status

•  But they will stay ;)

Page 11: Scala Macros

@adamwarski

WRITING A MACRO STEP-BY-STEP Goal – transform this:

debug(x*amount)

To:

println("x*amount = " + (x*amount))

So that it outputs: x*amount = 10.23

Page 12: Scala Macros

DEMO

WRITING A SIMPLE MACRO

Page 13: Scala Macros

@adamwarski

WHERE ARE MACROS USED? •  Slick •  Akka •  Async

•  Expecty

•  MacWire

examples are mostly from the projects’ websites

Page 14: Scala Macros

@adamwarski

SLICK @table(name="COFFEES") case class Coffee(

@column(name="NAME") name: String,

@column(name="PRICE") price: Double

)

val q = Queryable[Coffee]

val r = q.filter(_.price > 3.0).map(_.name)

Page 15: Scala Macros

@adamwarski

ASYNC val f1 = Future { beSlow(); 19 }

val f2 = Future { beSlow(); 23 }

val futureResult = for {

v1 <- f1

v2 <- f2

} yield v1 + v2

Page 16: Scala Macros

@adamwarski

ASYNC val futureResult = async {

val f1 = async { beSlow(); 19 }

val f2 = async { beSlow(); 23 }

await(f1) + await(f2)

}

Page 17: Scala Macros

@adamwarski

ASYNC val future = async {

val f1 = async { beSlow(); true }

val f2 = async { beSlow(); 42 }

if (await(f1)) await(f2) else 0

}

•  Also possible with Akka Dataflow & CPS (but that’s so ’09) •  Can also use for-comprehensions; but quickly gets tricky

Page 18: Scala Macros

@adamwarski

ERRORS •  Cryptic errors? •  Can be, if generated code doesn’t compile •  But we can provide user-friendly errors

context.error(

c.enclosingPosition,

"You can’t do that")

Page 19: Scala Macros

DEMO

EXPECTY & MACWIRE

Page 20: Scala Macros

@adamwarski

AND OTHERS! •  Akka 2.2 typed channels •  ScalaMock •  Typesafe Logging

•  …

Page 21: Scala Macros

@adamwarski

OTHER TYPES OF MACROS

•  Coming in Scala 2.11+

•  Some also available as a compiler plugin in 2.10

based on the examples from http://scalamacros.org/

Page 22: Scala Macros

@adamwarski

DEF MACROS •  What we’ve seen so far •  Look like a method invocation •  Generate code basing on:

•  The parameters •  Enclosing method/class •  Implicit lookups

Page 23: Scala Macros

@adamwarski

IMPLICIT MACROS •  Useful for Type Classes •  Available in Scala 2.10.2!

trait Showable[T] { def show(x: T): String }

def useShow[T](x: T)(implicit s: Showable[T]) = s.show(x)

implicit object IntShowable {

def show(x: Int) = x.toString }

Page 24: Scala Macros

@adamwarski

IMPLICIT MACROS We want to provide a “default implementation” for a type

trait Showable[T] { def show(x: T): String }

object Showable {

implicit def materialize [T]: Showable[T] =

macro ...

}

We can get access to T at compile-time and generate what’s needed

Page 25: Scala Macros

@adamwarski

IMPLICIT MACROS Works well with implicit search order

•  Current scope is first •  Implicits in scope •  Imported implicits

•  Then associated types: •  Companion objects •  Implicit scope of argument’s type •  Implicit scope of type arguments

Page 26: Scala Macros

@adamwarski

MACRO ANNOTATIONS Annotation-drive macros

•  Any definitions can be annotated

class identity extends StaticAnnotation {

def macroTransform(annottees: Any*) = macro ???

}

Page 27: Scala Macros

@adamwarski

MACRO ANNOTATIONS •  Annottees is:

•  Annotated class + companion object •  Method parameter, owner, companion

•  Can expand classes

•  Can create companion objects

Page 28: Scala Macros

@adamwarski

QUASIQUOTES •  Similar to string interpolators •  Extract from trees: val q"def $name[..$tparams](...$vparamss): $tpt

= $body” = methodTree

•  Pattern match tree match {

case q"def $name[..$tps](...$vps): $tpt

= $body” =>

}

Page 29: Scala Macros

@adamwarski

QUASIQUOTES Construct

•  Terms: q"future{ $body }" •  Types: tq"Future[$t]" •  Cases: cq"x => x" •  Patterns: pq"xs @ (hd :: tl)"

Page 30: Scala Macros

@adamwarski

POTENTIAL PROBLEMS •  Hard to write •  Code may be harder to understand •  And to debug

Page 31: Scala Macros

@adamwarski

WHEN TO WRITE A MACRO? •  Always think it through •  Lots of repeated, boilerplate code •  Unavoidable copy-paste (patterns)

•  Library code

macro: power => responsibility

Page 32: Scala Macros

@adamwarski

LINKS •  http://www.warski.org/blog/2012/12/starting-with-scala-

macros-a-short-tutorial/ •  http://scalamacros.org/ •  http://slick.typesafe.com/

•  https://github.com/scala/async

•  https://github.com/adamw/macwire

•  https://github.com/adamw/scala-macro-tutorial

Page 33: Scala Macros

@adamwarski

http://codebrag.com COME & GET A STICKER

Adam Warski @adamwarski