Scala Macro 现状介绍

原创
2018/05/01 19:34
阅读数 2.6K

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

展开阅读全文
打赏
1
3 收藏
分享
加载中
joymufeng博主

引用来自“L-trans”的评论

最近在看 java reflect 和 scala reflect,越看越深。却发现 reflect 也是实验性的。而到了 macro 感觉比较乱
scala macro 一直在易用性和灵活性之间做权衡,似乎 Scala 3 也没有找到完美的平衡点:https://www.scala-lang.org/blog/2018/04/30/in-a-nutshell.html
2018/05/04 19:21
回复
举报
最近在看 java reflect 和 scala reflect,越看越深。却发现 reflect 也是实验性的。而到了 macro 感觉比较乱
2018/05/04 18:23
回复
举报
更多评论
打赏
2 评论
3 收藏
1
分享
返回顶部
顶部