"动态"使用宏创建案例类

use*_*970 14 scala case-class scala-macros

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

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

Tra*_*own 22

首先是一些无耻的自我推销:Eugene Burmako和我将在明天的Scalar 2014上就类型提供者(一个密切相关的主题)进行讨论,我鼓励你看看我们在一起讨论的示例项目,如果你对这种事感兴趣.

虽然类型为宏不再被支持,你可以用基本完成同样的事情宏注释宏观天堂(其可作为斯卡拉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.
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后:

scala> @expand trait MyADT
defined trait MyADT
defined class Foo
defined class Bar
defined module Baz
Run Code Online (Sandbox Code Playgroud)

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

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

  • 谢谢!使用def宏,我是否正确地认为没有办法直接引用源中创建的类? (2认同)