(pour TL; DR, allez à la partie de gras)utilisant def-macros pour capturer le code source
J'ai un système de classe de type fermé propre avec sérialisation (détaché de maux de sérialisation POJO). Par exemple:
trait Expr
case class Const(i: Int) extends Expr
case class BinOp(a: Expr, b: Expr, op: Int) extends Expr
Mais dans les situations j'ai besoin de capturer une fermeture. Par exemple:
case class Map(a: Expr, fun: Expr => Expr) extends Expr
Maintenant, je l'avais résolu cette fois avec sérialisation POJO (ObjectOutputStream
etc.) pour la fun
. J'ai été gravement mordu dans les pieds, parce que je ne pouvais pas lire dans Scala 2.10 ce que j'avais sérialisé en 2.9. Et dans ce cas, j'ai vraiment besoin de m'assurer que je peux récupérer mon contenu indépendamment de la version Scala. J'ai pensé que je pourrais utiliser une macro pour faire une "sauvegarde" du code source, de sorte que si la désérialisation POJO échoue, je peux régénérer la fonction à partir de la source (en utilisant un compilateur in-situ /interprète).
Mon idée serait
object Map {
def apply(a: Expr, fun: Expr => Expr): Map = macro applyImpl
private def applyImpl = ???
def unapply(m: Map): Option[(Expr, Expr => Expr)] = Some(m.a -> m.fun)
}
trait Map extends Expr {
def a: Expr
def fun: Expr => Expr
}
implicit class ExprOps(val ex: Expr) extends AnyVal {
def map(fun: Expr => Expr) = Map(ex, fun)
}
Est-il possible de capturer facilement la source d'un appel comme
// |------------- source of this -------------|
someExpr.map { case Const(i) => Const(i*i); case x => x }
(Je pense aux besoins def-macro pour être déjà dans la map
fonction de ExprOps
).
Je ne pense pas que vous pouvez obtenir la source, mais vous pouvez obtenir 'Tree':' def applyImpl (c: Contexte) (a: c.Expr [Expr], amusant: c.Expr [Expr => Expr]): c.Expr [Map] = {val source = c.universe.show (fun.tree); ...} ' – senia
@senia merci pour le lien et le commentaire. Je n'ai pas besoin du code source original, en effet, car il ne sera pas montré (probablement) à l'utilisateur, je veux juste une source que je peux recompiler dans le même arbre, même si la version sérialisée de dire 'Tree' changements (donc je ne veux pas sérialiser l'arbre directement). Donc, je vais jeter un oeil à ce 'universe.show', qui pourrait en effet être suffisant. –