(для TL;DR перейдите к части, выделенной жирным шрифтом)
У меня есть чистая система классов закрытого типа с сериализацией (отдельно от проблем с сериализацией POJO). Например:
trait Expr
case class Const(i: Int) extends Expr
case class BinOp(a: Expr, b: Expr, op: Int) extends Expr
Но в ситуациях мне нужно зафиксировать замыкание. Например:
case class Map(a: Expr, fun: Expr => Expr) extends Expr
Теперь я решил это однажды с сериализацией POJO (ObjectOutputStream
и т. д.) для fun
. Меня сильно укусили за ноги, потому что я не мог прочитать в Scala 2.10 то, что сериализовал в 2.9. И в этом случае мне действительно нужно убедиться, что я могу вернуть свои вещи независимо от версии Scala.
Итак... Я подумал, что могу использовать макрос для создания «резервной копии» исходного кода, чтобы в случае сбоя десериализации POJO я мог регенерировать функцию из исходного кода (используя встроенный компилятор/интерпретатор).
Моя идея была бы
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)
}
Можно ли легко зафиксировать источник звонка, например
// |------------- source of this -------------|
someExpr.map { case Const(i) => Const(i*i); case x => x }
(Я предполагаю, что макрос def должен быть уже в функции map
ExprOps
).
Tree
:def applyImpl(c: Context)(a: c.Expr[Expr], fun:c.Expr[Expr => Expr]): c.Expr[Map] = { val source = c.universe.show(fun.tree); ... }
- person senia   schedule 07.05.2013Tree
изменится ( поэтому я не хочу сериализовать дерево напрямую). Итак, я посмотрю на этотuniverse.show
, этого действительно может быть достаточно. - person 0__   schedule 07.05.2013