“动态”使用宏创建案例类

时间:2014-04-03 22:43:02

标签: scala scala-macros case-class

我想创建一个密封的抽象和案例类的宏生成层次结构。有一个与http://docs.scala-lang.org/overviews/macros/typemacros.html类似的例子,但现在已经过时了。这还有可能吗?

我认为为某些指定的语法生成类型安全的AST会非常强大。理想情况下,IDE可以解析所有类。

1 个答案:

答案 0 :(得分:22)

首先进行一些无耻的自我推销:Eugene Burmako我明天type providersScalar 2014这个密切相关的主题发表演讲,我鼓励你去看一看如果您对此类事情感兴趣,我们会在the example project进行讨论。

虽然不再支持类型宏,但您可以使用macro annotations中的macro paradise完成相同的操作(可作为Scala 2.10和2.11的插件使用):

import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.Context

// Add constructor arguments here.
class expand extends StaticAnnotation {
  def macroTransform(annottees: Any*) = macro Expander.expand_impl
}

object Expander {
  def expand_impl(c: Context)(annottees: c.Expr[Any]*) = {
    import c.universe._

    annottees.map(_.tree) match {
      case List(q"trait $name") => c.Expr[Any](
        // Add your own logic here, possibly using arguments on the annotation.
        q"""
          sealed trait $name
          case class Foo(i: Int) extends $name
          case class Bar(s: String) extends $name
          case object Baz extends $name
        """
      )
      // Add validation and error handling here.
    }
  }
}

然后:

scala> @expand trait MyADT
defined trait MyADT
defined class Foo
defined class Bar
defined module Baz

您可以在编译时为注释添加参数,例如,允许您解析可用于生成ADT实现的外部资源。

宏观注释非常具有实验性,它们的状态仍然悬而未决 - 例如,无法保证它们将与Scala 2.12一起发布。使用普通的def宏和结构类型可以实现类似的东西(虽然不是很干净) - 请参阅上面链接的the example project以获取更多细节和一些演示。在任何情况下,这种机制都是许多人感兴趣的,包括Scala宏系统的开发人员,所以即使宏观注释在某些时候消失,也可能有某种方法来完成你在这里描述的内容。