mardi 22 octobre 2019

How to substitute objects in tree-like Scala case class instance with derived objects?

Suppose I have a set of case classes that represent constants, variables, and unary and binary operations on them, similar to one from "Case Classes and Pattern Matching" chapter in Programming in Scala:

abstract class Value {
    def basicEvaluate(varArray: Array[Double]): Double
    def evaluate(varArray: Array[Double]) = basicEvaluate(varArray)
}

case class Constant(d: Double) extends Value {
    override def basicEvaluate(varArray: Array[Double]) = d
}

case class Variable(i: Int) extends Value {    
    override def basicEvaluate(varArray: Array[Double]) = varArray(i)
}

case class Add(v1: Value, v2: Value) extends Value {
    override def basicEvaluate(varArray: Array[Double]) = v1.evaluate(varArray) + v2.evaluate(varArray)
}

...

Then, suppose I have some means to produce expression trees that reuse certain subexpressions many times, and I wish to be able to evaluate the expression efficiently, so that each distinct subexpression gets evaluated only once. For this reason, I introduce a trait

trait UsingCache extends Value {
    var cached: Option[Double] = None
    override def evaluate(varArray: Array[Double]) = {
        if (cached == None) {
            cached = Some(basicEvaluate(varArray))
        }
        cached.get
    }
}

Then, I can do the following:

val expr = new Variable(0) with UsingCache
val expr2 = new Add(expr, expr) with UsingCache
expr2.evaluate(Array(5.0))

and it works.

My question is - how to implement a function def extend(value: Value): UsingCache which would recursively replace each Value in the tree with a corresponding .. with UsingCache object? I wish to keep this logic decoupled from the individual subclasses of Value (e.g., when I add a new operation, it shouldn't contain any code specific for caching). Is there some way to do this using implicit conversion? Or some ideas how to use Scala reflection (I'm using Scala 2.12)?





Aucun commentaire:

Enregistrer un commentaire