Kevin Meredith
Kevin Meredith

Reputation: 41909

Mutability of an Object

Martin Odersky gave the Keynote talk for Scala Days 2013.

One slide was titled "When is an Object Mutable?" Its contents read as follow:

class Memo[T, U](fn: T => U) {

  val memo = new mutable.WeakHashMap[T, U]
  def apply(x: T) = memo.getOrElseUpdate(x, fn(x))
}

// an object is mutable if its (functional) behavior depends on its history

new Memo {i: Int => i + 1} // immutable

var ctr = 0;
new Memo { i: Int => ctr += i; ctr } // mutable

Please explain why the Memo examples are, respectively, immutable and mutable.

Upvotes: 0

Views: 161

Answers (2)

Beryllium
Beryllium

Reputation: 12998

A quote from Wikipedia

In some cases, an object is considered immutable even if some internally-used attributes change but the object's state appears to be unchanging from an external point of view. For example, an object that uses memoization to cache the results of expensive computations could still be considered an immutable object.

But I'd like to draw the attention to "could [...] be considered", so not everyone considers it to be immutable.

If you look at this Memo implementation using an immutable Map:

class Memo[T, U](val fn: T => U, map: Map[T, U]) {
  def this(fn: T => U) {
    this(fn, Map[T, U]())
  }

  def apply(x: T): (U, Memo[T, U]) = {
    if (map.contains(x)) {
      println("Cache hit")
      (map(x), this)
    } else {
      println("Cache miss")
      val result = fn(x)
      val newMap = map + ((x, result))
      (result, new Memo(fn, newMap))
    }
  }
}

there is no mutable internal state at all (it's delegated to the caller). But now we have the problem to differ between two degrees of immutability.

From a practical point of view, a memoizer must be functional, but its name/purpose implies mutability, even if it does not affect external behaviour.

Upvotes: 0

esycat
esycat

Reputation: 1364

In the first example, the provided function increments given value by 1. The result does not depend on any external state.

In the second example the result depends on ctr value that is some global state in relation to Memo. In other words, the global state, represented by ctr value, can influence the behavior and the result in the second example.

Upvotes: 3

Related Questions