0

Martin Odersky は Scala Days 2013 の基調講演を行いました。

1 つのスライドのタイトルは、「オブジェクトが可変になるのはいつですか?」というものでした。その内容は次のとおりです。

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

メモの例がそれぞれ不変および可変である理由を説明してください。

4

2 に答える 2

3

最初の例では、指定された関数が指定された値を 1 ずつインクリメントします。結果は外部状態に依存しません。

ctr2 番目の例では、結果はに関連するグローバルな状態である値に依存しますMemo。つまり、値で表されるグローバルな状態ctrは、2 番目の例の動作と結果に影響を与える可能性があります。

于 2013-07-07T04:00:36.793 に答える
0

ウィキペディアからの引用

場合によっては、内部で使用される属性の一部が変更されても、オブジェクトの状態が外部の観点からは変更されていないように見える場合でも、オブジェクトは不変と見なされます。たとえば、メモ化を使用して高価な計算の結果をキャッシュするオブジェクトは、依然として不変オブジェクトと見なすことができます。

しかし、「 [...] を考慮することができる」ことに注意を向けたいと思います

不変の 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))
    }
  }
}

変更可能な内部状態はまったくありません (呼び出し元に委譲されます)。しかし今、私たちは 2 つの程度の不変性を区別するという問題を抱えています。

実用的な観点から、メモライザーは機能的でなければなりませんが、その名前/目的は、外部の動作に影響を与えなくても、可変性を意味します。

于 2013-07-07T08:29:08.440 に答える