"динамически" создание классов case с макросами

Я хотел бы создать макросгенерированную иерархию закрытых абстрактных и case-классов. Был пример, подобный этому с http://docs.scala-lang.org/overviews/macros/typemacros.html, но теперь он устарел. Возможно ли это?

Я думаю, что было бы невероятно мощно генерировать безопасный тип AST для определенной грамматики. В идеале с помощью IDE, способной разрешать все классы.

Ответ 1

Сначала для некоторой бесстыдной саморекламы: Евгений Бурмако, и я рассказываю о типах поставщиков, тесно связанную тему, на Scalar 2014 завтра, и я рекомендую вам взглянуть на пример проекта мы собрались для разговора, если вы заинтересованы в этом.

В то время как макросы типа больше не поддерживаются, вы можете сделать практически то же самое с макрокомандами из 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 и структурных типов - см. примерный проект, приведенный выше для более подробной информации и некоторых демонстраций. В любом случае такой механизм представляет интерес для многих людей, в том числе разработчиков макросистемы Scala, поэтому, даже если макрокоманды исчезнут в какой-то момент по дороге, вероятно, будет какой-то способ выполнить то, что у вас есть описанных здесь.