Je vais commencer par un exemple. Voici un équivalent de List.fill
pour les n-uplets d'une macro dans 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!"
)
}
}
}
Nous pouvons utiliser cette méthode comme suit:
scala> TupleExample.fill(3)("hello")
res0: (String, String, String) = (hello,hello,hello)
Ce mec est un drôle d'oiseau dans une couple d'égards. Tout d'abord, l' arity
argument doit être un littéral entier, car nous avons besoin de l'utiliser au moment de la compilation. Dans les versions précédentes de la Scala, il n'y a aucun moyen (autant que je sache) pour une méthode à même de dire si l'un de ses arguments était au moment de la compilation littéral ou non.
Deuxièmement, l' Product
type de retour est un mensonge-la statique type de retour comprendra spécifiques arité et type d'élément déterminé par les arguments, comme indiqué ci-dessus.
Alors, comment aurais-je document de cette chose? Je ne suis pas attendre Scaladoc soutien à ce point, mais j'aimerais avoir un sens de conventions ou de meilleures pratiques (au-delà seulement de s'assurer que l'erreur de compilation de messages sont clairs) en cours d'exécution dans une méthode de la macro-avec sa potentiellement bizarre demandes-moins étonnant pour les utilisateurs d'un Scala 2.10 de la bibliothèque.
La plus mature des démonstrations de la nouvelle macro système (par exemple, ScalaMock, Slick, les autres énumérés ici) sont encore relativement sans-papiers au niveau de la méthode. Des exemples ou des pointeurs serait appréciée, y compris ceux provenant d'autres langues avec les mêmes systèmes macro.