class: center, middle # The Future of Scala Metaprogramming http://goo.gl/F29sd9 --- class: top # Talks * ⇒ Metaprogramming 2.0 - Eugene Burmako
https://youtu.be/wii5UPtu1_g (Scala Days 2016 NYC)
http://goo.gl/xUUxOE (Slides Scala Days 2016 Berlin) * ⇒ Dotty Linker:
...
- Dmitry Patrashko
https://youtu.be/h8KBLF0AgUc (Scala Days 2016 NYC)
http://goo.gl/XrGGtH (Slides Scala Days 2016 Berlin) * Scalan:
...
- Alexander Slesarenko * Data centric Metaprogramming - Vlad Ureche - https://youtu.be/83VfxITTNPE (Spark Summit Europe 2015) ??? Scalan: DSL development/compilation framework Vlad Ureche: using meta-programming to speed up applications --- class: top # Macros ``` type Macro = Code ⇒ Code ``` --- class: top # Macros ``` type Macro = Code ⇒ Code ``` * Treating programs as data * Transform programs * Compile-time reflection * Extending the language/compiler --- class: top # Macro support 2.10: Macro's introduced as experimental feature --- class: top # Macro support 2.10 - 2.11: Whitebox macros 2.11: Blackbox macros ??? Original plan was to stabalize blackbox macros --- # Scala.meta ![New and improved](newimproved.jpg) --- class: top # Macro support 2.10 - 2.12: Whitebox macros 2.11 - 2.12: Blackbox macros 2.10 - 2.12: scala.meta
Dotty: scala.meta
Scala Native: scala.meta
Scala.JS: scala.meta ??? --- class: top # Scala.meta * Easier and less boilerplate --- class: top # Scala.meta * Easier and less boilerplate * Compiler implementation independent
dotty, scala native, scala.js --- class: top # Scala.meta * Easier and less boilerplate * Compiler implementation independent
dotty, scala native, scala.js * IDE support --- class: top # Scala.meta * Easier and less boilerplate * Compiler implementation independent
dotty, scala native, scala.js * IDE support * Improved parsing (dialects, formatting) --- class: top # Scala.meta roadmap: * Typechecking, name resolution, implicit interference * Inline macros * 2.10, 2.12, scala.js --- class: top # Example: @main ``` @main object Test { println("hello world") } ``` --- class: top # Example: @main ``` @main object Test { println("hello world") } ``` ↓ ``` object Test { def main(args: Array[String]): Unit = { println("hello world") } } ``` --- class: top # Example: @main scala.reflect ``` class main extends scala.annotation.StaticAnnotation { def macroTransform(annottees: Any*): Any = macro Macros.impl } import scala.reflect.macros.whitebox.Context object Macros { def impl(c: Context)(annottees: c.Tree*): c.Tree = { import c.universe. val q"object $name { ..$stats }" = annottees.head val main = q""" def main(args: Array[String]): Unit = { ..$stats } """ q"object $name { $main }" } } ``` ??? Bad: boilerplate: same amount Good: quasiquotes --- class: top # Example: @main scala.meta ``` import scala.meta._ class main extends scala.annotation.StaticAnnotation { inline def apply(defn: Any) = meta { val q"object $name { ..$stats }" = defn val main = q""" def main(args: Array[String]): Unit = { ..$stats } """ q"object $name { $main }" } } ``` --- class: top # Example: @main scala.meta ``` import scala.meta._ class main extends scala.annotation.StaticAnnotation { inline def apply(defn: Any) = meta { val q"object $name { ..$stats }" = defn val main = q""" def main(args: Array[String]): Unit = { ..$stats } """ q"object $name { $main }" } } ``` ``` @main object Test { println("hello world") } ``` --- class: top # Example: @main scala.meta ``` import scala.meta._ class main extends scala.annotation.StaticAnnotation { inline def apply(defn: Any) = meta { val q"object $name { ..$stats }" = defn val main = q""" def main(args: Array[String]): Unit = { ..$stats } """ q"object $name { $main }" } } ``` ``` object Test { def main(args: Array[String]): Unit = { println("hello world") } } ``` --- class: top # Other macro uses * Scalafmt * Automatic serialization ([Play JSON](https://github.com/playframework/playframework/blob/afd06b38241e158229393ab68724a2cbd82d444d/framework/src/play-json/src/main/scala/play/api/libs/json/JsMacroImpl.scala), [Pickling](https://github.com/scala/pickling/blob/4f5dd03ae103c4e6d42eae1c14b3180a1813bae4/core/src/main/scala/scala/pickling/generator/PicklingMacros.scala)) * Debugging (e.g. [print all variables in scope](https://github.com/adamw/scala-macro-debug)) * Performance improvements --- class: top # Performance improvements ``` if(logger.isErrorEnabled) { logger.error(expensiveArgument()); } ``` ⇔ ``` logger.error(expensiveArguments()); ``` --- class: top # Performance improvements ``` val arr = (1 to 10000000).toArray arr.reduce(_ + _).toDouble / arr.length ``` ⇔ ``` 5000000.5 ``` ??? It will take scala about a second to determine that the above is indeed that number --- class: top # Dotty TASTY * Typed AST * Binary distribution format for dotty ??? Distribution format of Dotty scala binaries --- class: top # Dotty linker Whole-program optimization * Dead code elimination *for your specific usage* * Specialization * Inlining * Virtual dispatch removal * Performance rewrites ??? Specialization normally not viable: 10^n combinations n= program args --- class: top # Rewrite rules ``` import dotty.linker._ @rewrites object LoggerOptimization { def error(x: Seq[Int]) = Rewrite(from = logger.error(s), to = if(logger.isErrorEnabled) logger.error(s) else ()) ``` ??? Readability or performance: why not both? --- class: top # Rewrite rules ``` import dotty.linker._ @rewrites object LoggerOptimization { def error(x: Seq[Int]) = Rewrite(from = logger.error(s), to = if(logger.isErrorEnabled) logger.error(s) else ()) ``` Correctness: automatic scalacheck tests (planned) --- class: top # Summary ##### Scala.meta * simplifies meta-programming in Scala * Only macro system of dotty, scala native, scala JS * High-fidelity parsing * No feature parity yet --- class: top # Summary ##### Scala.meta * simplifies meta-programming in Scala * Only macro system of dotty, scala native, scala JS * High-fidelity parsing * No feature parity yet ##### Scala linker * Whole-program optimization * Rewrite rules (performance oriented) --- class: top # Summary ##### Scala.meta * simplifies meta-programming in Scala * Only macro system of dotty, scala native, scala JS * High-fidelity parsing * No feature parity yet ##### Scala linker * Whole-program optimization * Rewrite rules (performance oriented) http://goo.gl/F29sd9