Metaprogramming 2.0 (ScalaDays Berlin 2016)

This talk explains the status of Scalameta, demonstrates key features, presents the early adopters and publishes our plans for the future. The centerpiece of the talk is the demo of a new macro system for Scala, which is no longer part of Scalameta. Nonetheless, the talk still does a good job of showcasing potential usecases for Scalameta and highlighting contributions from our amazing community.
展开查看详情

1. Metaprogramming 2.0 Eugene Burmako (@xeno by) ´ Ecole Polytechnique F´ ed´ erale de Lausanne http://scalameta.org/ 17 June 2016 This talk was presented and recorded at ScalaDays Berlin 2016: https://www.youtube.com/watch?v=IPnd SZJ1nM

2.Today’s talk ▶ What is scala.meta? ▶ What can scala.meta do? ▶ Why should you care? ▶ What will happen next? 2

3.scala.meta is a dream 3

4.scala.meta is an active project 4

5.scala.meta is a community 5

6.scala.meta is a product 6

7.scala.meta is officially endorsed 7

8.Part 1: What can scala.meta do?

9.Project status ▶ 17 Jun 2014: “Easy metaprogramming for everyone!” 9

10.Project status ▶ 17 Jun 2014: “Easy metaprogramming for everyone!” ▶ 17 Jun 2016: 3191 commits and 27 milestones later... 10

11.Project status ▶ 17 Jun 2014: “Easy metaprogramming for everyone!” ▶ 17 Jun 2016: 3191 commits and 27 milestones later... ▶ We’re finally releasing v1.0! 11

12.Supported functionality ▶ Vendor-neutral tree interchange format ▶ High-fidelity parsing ▶ First-class tokens 12

13.Parsing: easy to get started scala> import scala.meta._ import scala.meta._ scala> "x + y".parse[Term] res0: scala.meta.parsers.Parsed[scala.meta.Term] = x + y 13

14.Parsing: remember all syntactic details scala> import scala.meta._ import scala.meta._ scala> "x + y".parse[Term] res0: scala.meta.parsers.Parsed[scala.meta.Term] = x + y scala> "x + y // hello world".parse[Term] res1: scala.meta.parsers.Parsed[scala.meta.Term] = x + y // hello world 14

15.Tokens: remember all syntactic details scala> val add = "x + y // hello world".parse[Term].get add: scala.meta.Term = x + y // hello world scala> add.tokens res2: scala.meta.tokens.Tokens = Tokens(, x, , +, , y, , // hello world, ) 15

16.Tokens: remember all syntactic details scala> val add = "x + y // hello world".parse[Term].get add: scala.meta.Term = x + y // hello world scala> add.tokens res2: scala.meta.tokens.Tokens = Tokens(, x, , +, , y, , // hello world, ) scala> add.tokens.structure res3: String = Tokens(BOF [0..0), x [0..1), [1..2), + [2..3), [3..4), y [4..5), [5..6), // hello world [6..20), EOF [20..20)) 16

17.Parsing: support for dialects scala> val sbtBuild = new File(".../project/plugins.sbt") sbtBuild: java.io.File = .../project/plugins.sbt 17

18.Parsing: support for dialects scala> val sbtBuild = new File(".../project/plugins.sbt") sbtBuild: java.io.File = .../project/plugins.sbt scala> scala.meta.dialects.Sbt0136(sbtBuild).parse[Source] res4: scala.meta.parsers.Parsed[scala.meta.Source] = addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "0.8.1") addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2") ... 18

19.Quasiquotes: stealing better parts of scala.reflect scala> q"x + y" res5: scala.meta.Term.ApplyInfix = x + y scala> val q"$a + $b" = res5 a: scala.meta.Term = x b: scala.meta.Term.Arg = y 19

20.Part 2: Why should you care?

21.Why should you care? Scala.meta provides unique features that enable much better tools 21

22.Case study: Macros

23.Macros are dead? 23

24.Macros are bad ▶ Hard to write ▶ Don’t work with tools well 24

25.Example: the @main macro @main object Test { println("hello world") } object Test { def main(args: Array[String]): Unit = { println("hello world") } } 25

26.Example: the @main macro class main extends scala.annotation.StaticAnnotation { def macroTransform(annottees: Any*): Any = macro Macros.impl } 26

27.Example: the @main macro 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 }" } } 27

28.Really hard to write! 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 }" } } 28

29.Don’t work with tools well ▶ If we make a typo in macro code, IDEs won’t help us ▶ If we change macro code, SBT isn’t going to recompile 29