I was writing code for something like an array with variable dimensions. What I do is to maintain a linear underlying collections and wrap it up with index access methods. Since the dimension of the data structure is not known, I write something like
def apply(i: Int*): Double = ...
And it works perfectly. However, I cannot do the same thing to update method and operators like +=, so I end up writing methods like
def set(v: Double, i: Int*) ...
def add(v: Double, i: Int*) ...
which is fine but not what I really want. I guess the problem about update may be fixed in two ways:
The problem about += seems more complicated and it even exists when the index is of fixed length. Maybe we can add an object that has += operator and use this(...) to get the object (so that this(...) += v will invoke some method as we expect), but that will conflict with the apply method.
If anyone has solution to any of the above questions or has a reason why we shouldn't be able to write code like this, please share your ideas! Thanks~
The simplest solution I see right now is to have many different overloads of update
for every dimension that you want to support. Say that you can determine that the maximum dimension that you'll ever use is 10, this means that you'll need 10 overloads. This might not seem very practical, but i can easily be abstracted away so it is very much practical actually:
trait MultiKeyUpdate[K, V] {
def doUpdate( k: K* )( v: V )
def update(k1: K, v: V) { doUpdate( k1 )( v ) }
def update(k1: K, k2: K, v: V) { doUpdate( k1, k2 )( v ) }
def update(k1: K, k2: K, k3: K, v: V) { doUpdate( k1, k2, k3 )( v ) }
// ... and so on, up until max dimension ...
}
Usage:
class C extends MultiKeyUpdate[Int, Double] {
def apply(i: Int*): Double = {
println("Returning element " + i.mkString("[",",","]"))
123
}
def doUpdate( i: Int* )( v: Double ) {
println("Updating element " + i.mkString("[",",","]") + " to value " + v)
}
}
And some test in the REPL:
scala> val o = new C
o: C = C@12798c1
scala> o(1,2,3)
Returning element [1,2,3]
res3: Double = 123.0
scala> o(1,2,3) = 5.0
Updating element [1,2,3] to value 5.0
scala> o(1,2,3) += 7.0
Returning element [1,2,3]
Updating element [1,2,3] to value 130.0