Documentando macros Scala 2.10
documentation scala-2.10 (1)
Comenzaré con un ejemplo. Aquí hay un equivalente de List.fill
para tuplas como una macro en Scala 2.10:
import scala.language.experimental.macros
import scala.reflect.macros.Context
object TupleExample {
def fill[A](arity: Int)(a: A): Product = macro fill_impl[A]
def fill_impl[A](c: Context)(arity: c.Expr[Int])(a: c.Expr[A]) = {
import c.universe._
arity.tree match {
case Literal(Constant(n: Int)) if n < 23 => c.Expr(
Apply(
Select(Ident("Tuple" + n.toString), "apply"),
List.fill(n)(a.tree)
)
)
case _ => c.abort(
c.enclosingPosition,
"Desired arity must be a compile-time constant less than 23!"
)
}
}
}
Podemos usar este método de la siguiente manera:
scala> TupleExample.fill(3)("hello")
res0: (String, String, String) = (hello,hello,hello)
Este tipo es un pájaro extraño en un par de aspectos. Primero, el argumento arity
debe ser un entero literal, ya que necesitamos usarlo en tiempo de compilación. En versiones anteriores de Scala, no había forma (hasta donde yo sé) de que un método siquiera dijera si uno de sus argumentos era un literal en tiempo de compilación o no.
En segundo lugar, el tipo de devolución del Product
es un mentira: el tipo de devolución estática incluirá la aridad específica y el tipo de elemento determinado por los argumentos, como se muestra arriba.
Entonces, ¿cómo documentaría esto? No espero el soporte de Scaladoc en este momento, pero me gustaría tener una idea de las convenciones o mejores prácticas (más allá de solo asegurarme de que los mensajes de error en tiempo de compilación son claros) que harían que se ejecute en un método macro: con su demandas potencialmente extrañas, menos sorprendentes para los usuarios de una biblioteca Scala 2.10.
Las demostraciones más maduras del nuevo macro sistema (p. Ej., ScalaMock , Slick , las demás enumeradas here ) todavía están relativamente indocumentadas a nivel de método. Se apreciarán todos los ejemplos o indicadores, incluidos los de otros lenguajes con sistemas macro similares.