- 快召唤伙伴们来围观吧
- 微博 QQ QQ空间 贴吧
- 文档嵌入链接
- 复制
- 微信扫一扫分享
- 已成功复制到剪贴板
Metaprogramming 2.0 (ScalaDays Berlin 2016)
展开查看详情
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