(对于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
现在,我已经用ObjectOutputStream
的POJO序列化(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-macro必须已经在map
的{{1}}函数中。
答案 0 :(得分:0)
文本替换宏在这种事情上很棒。 Scala没有附带它们,但考虑编写自己的!改变,例如。
{# case Const(i) => Const(i*i); case x => x #}
到
({ case Const(i) => Const(i*i); case x => x }, """case Const(i) => Const(i*i); case x => x""")
应该很容易;那么你只需要在编译之前进行预处理。如果您希望IDE不会被不同的行长度混淆,可以将字符串存储在单独的对象中,例如
{# _+7 #}/*STORE*/
转到
({_+7}, Store.aW4)
...
object Store {
val aW4 = """_+7"""
}
//(EOF)
(为了获得最佳结果,base-64对捕获的文本进行编码。只要您以递归方式工作并且意识到可能发生嵌套,嵌套就能正常工作。)