1. Scala Macro
Scala Macro 是 Scala 2.10 版本增加的一个新的语言特性,让开发者可以在编译期动态修改/生成代码,为开发工作提供了很大的灵活性。Scala Macro 发展的高峰是 Scala 2.11 版本,增加更多新特性,其中最耀眼的便是QUASIQUOTES,它可以帮助开发者屏蔽编译器底层的细节,很大程度上简化了Macro的编写工作。到了Scala 2.12,Scala Macro 基本上没有太多变化,并且直到目前为止,Scala Macro 一直被打着EXPERIMENTAL标签,冥冥之中似乎预示着不好的征兆,果然 Scala Macro 最终还是被官方抛弃了,取而代之的是在 Dotty 中重新实现了,并且将会在2020年的 Scala 3.0 中发布。其实早在2018年的3月17日,Scala Macro 的核心作者 Eugene Burmako 就已经宣布放弃 Scala Macro 了,似乎也是在为 Scala 3.0 做准备。
2. Scala Meta
在 Scala Macro 发展过程中衍生了另外一个项目 Scala Meta , 本来雄心壮志要取代现有的 Scala Macro,可是走着走着却跑偏了,现在的目标是面向开发工具提供服务,典型的衍生项目是 Scalafmt,可以为开发者提供代码格式化服务。
3. 当前如何使用 Scala Macro ?
从 Scala 2.11 开始,Scala Macro 已经被合并至 Scala Reflect ,所以只要在项目中添加 Scala Reflect 依赖便可以进行Macro开发了:
libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.12.4"
有意思的是运行时Reflect和Macro共享底层的基础API,这意味着二者可以通过底层的API进行交互。在开发Macro时,可以使用 Runtime Reflect ,例如:
import scala.reflect.macros.blackbox.Context import scala.language.experimental.macros import scala.reflect.runtime.{ universe => ru }
object Macros { def allClasses: List[String] = macro allClassesImpl def allClassesImpl(c: Context) = { import c.universe._
val clsList =
ru
.runtimeMirror(this.getClass.getClassLoader)
.staticPackage("models").typeSignature.decls
.filter(s => s.isClass && s.asClass.isCaseClass)
.map{ s =>
s.asClass.typeSignature
s.fullName
}.toList
q"$clsList"
} }
在Macro方法实现中,可以通过 runtime universe 读取 models package 下的类列表。这只是一个示例用于说明 Scala Reflect 的run time和compile time可以很好的一起协作,但是由于JVM 类加载机制,上面的代码其实无法工作,每次运行读取的类列表都可能不同。另外,在进行Macro开发时,要注意配合构建工具的增量编译以及热加载。
更详细内容请参考:官方开发文档。
我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3mbt9sda0eo0w