Is immutableHashMapMemo the same as this function I wrote?
// The memoize method is inspired by
// https://clojuredocs.org/clojure.core/memoize
// Returning a memoized version of a referentially transparent function. The
// memoized version of the function keeps a cache of the mapping from arguments
// to results and, when calls with the same arguments are repeated often, has
// better performance at the expense of higher memory use.
def memoize[F, T](f: F => T): F => T = {
val hash = scala.collection.mutable.Map[F, T]()
def mem(i: F): T = {
hash.getOrElse(i, locally {
val v: T = f(i)
hash(i) = v
v
})
}
mem
}
Do you mean better to use getOrElseUpdate rather than making an explicit update in the 2nd argument of getOrElse? Why better, because it is more efficient, or more readable, or more idiomatic, or …?
Yes, that’s nicer and shorter, thanks for the free refactoring
BTW is there an advantage of returning an anonymous function rather than than a local function object?
def memoize[F, T](f: F => T): F => T = {
val hash = scala.collection.mutable.Map[F, T]()
def mem(i: F): T = hash.getOrElseUpdate(i, f(i))
mem
}
I often suppose that the compiler is optimization, when in fact perhaps it is not. I.e., I normally implicitly suppose that those two forms compile the same way. And if not, then the jvm optimization will treat them the same way after a bit of warming up.
That’s just the obvious default implementation in the Map trait. If you use Scala 2.13, you will get a HashMap as the underlying implementation for a mutable.Map and this class indeed overwrites the getOrElseUpdate method:
So, getOrElseUpdate indeed shaves off a few cycles by avoiding re-computing the hash, re-looking up the index.