使用宏动态创建case类

14

我希望创建一个由宏生成的密封抽象和case类的层次结构。这里有一个类似的示例:http://docs.scala-lang.org/overviews/macros/typemacros.html,但现在已经过时了。 这仍然可行吗?

我认为,为某些指定的语法生成类型安全的AST将非常强大。最理想的情况是,IDE能够解析所有类。

1个回答

25

首先是一些不要脸的自我推广:Eugene Burmako 和我将在明天的 Scalar 2014 上就类型提供者这个密切相关的话题发表讲话,如果你对这种东西感兴趣,我建议你看一下我们为演讲准备的示例项目

虽然类型宏已经不再支持,但你可以使用宏注解宏乐园(可作为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 宏和结构类型也可以实现类似的功能(虽然不太干净)--请参阅上面链接的示例项目以获取更多详细信息和演示。无论如何,这种机制都受到许多人的关注,包括 Scala 宏系统的开发人员,因此即使宏注解最终消失了,也很可能有某种方法来实现您在此处描述的内容。


1
完全离题:该死,我真希望早点知道那个会议。我已经报名了,尽管我怀疑在活动前一天是否还有剩余门票 :) - Patryk Ćwiek
如果有该演示的视频,将其链接回这里会很棒。 - user833970
不确定视频,但 Eugene 和我明天会发布幻灯片。 - Travis Brown
2
谢谢!使用 def 宏,是不是无法在源代码中直接引用所创建的类? - user833970
1
这似乎无法在Scala 2.12.1中工作,即使警告已经修复。 @expand trait Whatever@expand case class Whatever 将创建一个类型,但与准引用字符串中的代码无关。 - Jeff Schwab
1
对于2.11.7版本,我发现需要在REPL中包含Paradise jar才能使其工作,例如:wget http://central.maven.org/maven2/org/scalamacros/paradise_2.11.6/2.1.0/paradise_2.11.6-2.1.0.jarscala -Xplugin:paradise_2.11.6-2.1.0.jar - Mark Butler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接