(для TL; DR, перейти к смелой части лиц)Использования DEF-макросов, чтобы захватить исходный код
Я имею чистую замкнутую систему класса типа с сериализацией (оторванную от 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); ...} ' – senia
@senia спасибо за ссылку и комментарий. Мне не нужен исходный код, потому что он не будет отображаться (возможно) пользователю, я просто хочу, чтобы источник, который я мог перекомпилировать в одно и то же дерево, даже если сериализованная версия говорит 'Tree' (поэтому я не хочу сериализовать дерево напрямую). Итак, я посмотрю на это 'universe.show', которого действительно может быть достаточно. –