SCALA MACROS
Adam Warski, JavaZone 2013
@adamwarski
@adamwarski
ATTEND THIS TALK IF …
… you are curious what a macro is
… you are wondering how to write a macro in Scala
… yo...
@adamwarski
WHAT IS A MACRO?
•  Macro (large): expands into something larger
•  Function: code => code!
•  Invoked at buil...
@adamwarski
SCALA MACROS
•  Written in Scala
•  Have access to and can manipulate the AST
•  Use compiler/reflection APIs
...
@adamwarski
MACROS IN OTHER
LANGUAGES
C/C++ – preprocessor
•  #define BUFFER_SIZE 1024
•  #define min(X, Y) ((X) < (Y) ? (...
@adamwarski
MOTIVATION TO ADD
MACROS TO SCALA
(it’s not a lean language already!)
ü  Remove boilerplate
ü  Replace run-t...
@adamwarski
REACTIONS TO MACROS
Mixed ;)
@adamwarski
PLAN FOR THE NEXT
50 MINUTES
1.  How to write a simple macro
2.  Where macros are used now?
3.  Upcoming new t...
@adamwarski
ABOUT ME
During the day: coding @ SoftwareMill
SoftwareMill: a great software house!
Afternoon: playgrounds, D...
@adamwarski
“DEF” MACROS
•  Available since Scala 2.10 (Jan 2013)
•  Only one type of many possible macro types
•  Experim...
@adamwarski
WRITING A MACRO
STEP-BY-STEP
Goal – transform this:
debug(x*amount)
To:
println("x*amount = " + (x*amount))
So...
DEMO
WRITING A SIMPLE MACRO
@adamwarski
WHERE ARE MACROS
USED?
•  Slick
•  Akka
•  Async
•  Expecty
•  MacWire
examples are mostly from the projects’ ...
@adamwarski
SLICK
@table(name="COFFEES") case class Coffee(
@column(name="NAME") name: String,
@column(name="PRICE") price...
@adamwarski
ASYNC
val f1 = Future { beSlow(); 19 }
val f2 = Future { beSlow(); 23 }
val futureResult = for {
v1 <- f1
v2 <...
@adamwarski
ASYNC
val futureResult = async {
val f1 = async { beSlow(); 19 }
val f2 = async { beSlow(); 23 }
await(f1) + a...
@adamwarski
ASYNC
val future = async {
val f1 = async { beSlow(); true }
val f2 = async { beSlow(); 42 }
if (await(f1)) aw...
@adamwarski
ERRORS
•  Cryptic errors?
•  Can be, if generated code doesn’t compile
•  But we can provide user-friendly err...
DEMO
EXPECTY & MACWIRE
@adamwarski
AND OTHERS!
•  Akka 2.2 typed channels
•  ScalaMock
•  Typesafe Logging
•  …
@adamwarski
OTHER TYPES OF
MACROS
•  Coming in Scala 2.11+
•  Some also available as a compiler plugin in 2.10
based on th...
@adamwarski
DEF MACROS
•  What we’ve seen so far
•  Look like a method invocation
•  Generate code basing on:
•  The param...
@adamwarski
IMPLICIT MACROS
•  Useful for Type Classes
•  Available in Scala 2.10.2!
trait Showable[T] { def show(x: T): S...
@adamwarski
IMPLICIT MACROS
We want to provide a “default implementation” for a type
trait Showable[T] { def show(x: T): S...
@adamwarski
IMPLICIT MACROS
Works well with implicit search order
•  Current scope is first
•  Implicits in scope
•  Impor...
@adamwarski
MACRO ANNOTATIONS
Annotation-drive macros
•  Any definitions can be annotated
class identity extends StaticAnn...
@adamwarski
MACRO ANNOTATIONS
•  Annottees is:
•  Annotated class + companion object
•  Method parameter, owner, companion...
@adamwarski
QUASIQUOTES
•  Similar to string interpolators
•  Extract from trees:
val q"def $name[..$tparams](...$vparamss...
@adamwarski
QUASIQUOTES
Construct
•  Terms: q"future{ $body }"
•  Types: tq"Future[$t]"
•  Cases: cq"x => x"
•  Patterns: ...
@adamwarski
POTENTIAL
PROBLEMS
•  Hard to write
•  Code may be harder to understand
•  And to debug
@adamwarski
WHEN TO WRITE A
MACRO?
•  Always think it through
•  Lots of repeated, boilerplate code
•  Unavoidable copy-pa...
@adamwarski
LINKS
•  http://www.warski.org/blog/2012/12/starting-with-scala-
macros-a-short-tutorial/
•  http://scalamacro...
@adamwarski
http://codebrag.com
COME & GET A STICKER
Adam Warski @adamwarski
Upcoming SlideShare
Loading in …5
×

Scala Macros

2,054 views

Published on

JavaZone 2013 Scala Macros

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,054
On SlideShare
0
From Embeds
0
Number of Embeds
309
Actions
Shares
0
Downloads
18
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Scala Macros

  1. 1. SCALA MACROS Adam Warski, JavaZone 2013 @adamwarski
  2. 2. @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
  3. 3. @adamwarski WHAT IS A MACRO? •  Macro (large): expands into something larger •  Function: code => code! •  Invoked at build/compile-time
  4. 4. @adamwarski SCALA MACROS •  Written in Scala •  Have access to and can manipulate the AST •  Use compiler/reflection APIs •  Type-safe
  5. 5. @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
  6. 6. @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
  7. 7. @adamwarski REACTIONS TO MACROS Mixed ;)
  8. 8. @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
  9. 9. @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
  10. 10. @adamwarski “DEF” MACROS •  Available since Scala 2.10 (Jan 2013) •  Only one type of many possible macro types •  Experimental status •  But they will stay ;)
  11. 11. @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
  12. 12. DEMO WRITING A SIMPLE MACRO
  13. 13. @adamwarski WHERE ARE MACROS USED? •  Slick •  Akka •  Async •  Expecty •  MacWire examples are mostly from the projects’ websites
  14. 14. @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)
  15. 15. @adamwarski ASYNC val f1 = Future { beSlow(); 19 } val f2 = Future { beSlow(); 23 } val futureResult = for { v1 <- f1 v2 <- f2 } yield v1 + v2
  16. 16. @adamwarski ASYNC val futureResult = async { val f1 = async { beSlow(); 19 } val f2 = async { beSlow(); 23 } await(f1) + await(f2) }
  17. 17. @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
  18. 18. @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")
  19. 19. DEMO EXPECTY & MACWIRE
  20. 20. @adamwarski AND OTHERS! •  Akka 2.2 typed channels •  ScalaMock •  Typesafe Logging •  …
  21. 21. @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/
  22. 22. @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
  23. 23. @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 }
  24. 24. @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
  25. 25. @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
  26. 26. @adamwarski MACRO ANNOTATIONS Annotation-drive macros •  Any definitions can be annotated class identity extends StaticAnnotation { def macroTransform(annottees: Any*) = macro ??? }
  27. 27. @adamwarski MACRO ANNOTATIONS •  Annottees is: •  Annotated class + companion object •  Method parameter, owner, companion •  Can expand classes •  Can create companion objects
  28. 28. @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” => }
  29. 29. @adamwarski QUASIQUOTES Construct •  Terms: q"future{ $body }" •  Types: tq"Future[$t]" •  Cases: cq"x => x" •  Patterns: pq"xs @ (hd :: tl)"
  30. 30. @adamwarski POTENTIAL PROBLEMS •  Hard to write •  Code may be harder to understand •  And to debug
  31. 31. @adamwarski WHEN TO WRITE A MACRO? •  Always think it through •  Lots of repeated, boilerplate code •  Unavoidable copy-paste (patterns) •  Library code macro: power => responsibility
  32. 32. @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
  33. 33. @adamwarski http://codebrag.com COME & GET A STICKER Adam Warski @adamwarski

×