Your SlideShare is downloading. ×
0
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Scala Macros
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Scala Macros

1,085

Published on

JavaZone 2013 Scala Macros

JavaZone 2013 Scala Macros

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

No Downloads
Views
Total Views
1,085
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
18
Comments
0
Likes
3
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. SCALA MACROS Adam Warski, JavaZone 2013 @adamwarski
  • 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. @adamwarski WHAT IS A MACRO? •  Macro (large): expands into something larger •  Function: code => code! •  Invoked at build/compile-time
  • 4. @adamwarski SCALA MACROS •  Written in Scala •  Have access to and can manipulate the AST •  Use compiler/reflection APIs •  Type-safe
  • 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. @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. @adamwarski REACTIONS TO MACROS Mixed ;)
  • 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. @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. @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. @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. DEMO WRITING A SIMPLE MACRO
  • 13. @adamwarski WHERE ARE MACROS USED? •  Slick •  Akka •  Async •  Expecty •  MacWire examples are mostly from the projects’ websites
  • 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. @adamwarski ASYNC val f1 = Future { beSlow(); 19 } val f2 = Future { beSlow(); 23 } val futureResult = for { v1 <- f1 v2 <- f2 } yield v1 + v2
  • 16. @adamwarski ASYNC val futureResult = async { val f1 = async { beSlow(); 19 } val f2 = async { beSlow(); 23 } await(f1) + await(f2) }
  • 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. @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. DEMO EXPECTY & MACWIRE
  • 20. @adamwarski AND OTHERS! •  Akka 2.2 typed channels •  ScalaMock •  Typesafe Logging •  …
  • 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. @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. @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. @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. @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. @adamwarski MACRO ANNOTATIONS Annotation-drive macros •  Any definitions can be annotated class identity extends StaticAnnotation { def macroTransform(annottees: Any*) = macro ??? }
  • 27. @adamwarski MACRO ANNOTATIONS •  Annottees is: •  Annotated class + companion object •  Method parameter, owner, companion •  Can expand classes •  Can create companion objects
  • 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. @adamwarski QUASIQUOTES Construct •  Terms: q"future{ $body }" •  Types: tq"Future[$t]" •  Cases: cq"x => x" •  Patterns: pq"xs @ (hd :: tl)"
  • 30. @adamwarski POTENTIAL PROBLEMS •  Hard to write •  Code may be harder to understand •  And to debug
  • 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. @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. @adamwarski http://codebrag.com COME & GET A STICKER Adam Warski @adamwarski

×