Calculate two lazy vals depending on each other

I have a class representing square matrices. I’m calculating the inverse matrix lazily, as it is expensive to calculate, and deterministic.


  case class sqMatrix(val dim: Int, val tabulate: (Int, Int) => Double) {
    ...
    lazy val inverse: sqMatrix = { ... }
   ...
}    

I’d like to add the determinant calculation. I cannot calculate the determinate from the inverse, but I can modify the inverse calculation code to calculate both the inverse and the determinant at the same time.

What is the best way to handle this? I could create a calc-inverse-and-determinant function which returns a tuple, make that a lazy value, and create determinant and inverse lazy values which simply access the ._1, and ._2 of that tuple. But that’s a lazy value which is really not used for anything but an intermediate value. Making it lazy makes it allocate a slot in the class. Not so bad, I suppose but ugly.

Any suggestion? Of course I want to avoid running the code twice, independent of whether the user asks for the determinant or for the inverse or both.

I think you can have

lazy val (inverse, determinant) = { 
  ... // calculate i and d
  (i, d)
}

and both will get calculated when you access either of them. The optimizer in recent Scala versions can optimize intermediate tuples away, but I’m not sure whether he could also do that when it’s a lazy val. That should be verified.

3 Likes

Yes, this seems tow work well. Thanks @Jasper-M for the clever solution.