2

この質問はもう少し理論的です。プライベートな可変リストまたはマップを保持するオブジェクトがあり、その拡張は追加のみです。オブジェクト自体は機能的であり、機能的に透明であり、すべての外観に対して不変であると私は主張できると思います。だから例えば私は持っています

import scala.collection.mutable.Map

case class Foo(bar:String)

object FooContainer {
  private val foos = Map.empty[String, Foo]

  def getFoo(fooName:String) = foos.getOrElseUpdate(fooName, Foo(fooName))
}

私はリストで同様のケースを行うことができます。今、私は本当に機能していると想像しています。スレッドセーフを確保する必要があります。これは、ロック、同期、またはアトミック参照を使用するだけで実行できると思います。私の質問は、これはすべて必要十分であるということです、それは一般的な慣習ですか、この行動のための確立されたパターンはありますか?

4

2 に答える 2

2

「機能的」というのは本当に間違った言葉だと思います。上に示した正確な例は、その出力がその入力によってのみ定義され、したがって(目に見える)副作用がないという意味で「純粋」と呼ぶことができます。それは内部状態を隠しているので、実際にはそれは不純です。

関数は、同じ引数値が与えられた場合、常に同じ結果値を評価します。関数の結果値は、プログラムの実行が進むにつれて、またはプログラムの異なる実行間で変化する可能性のある非表示の情報や状態に依存することはできません。また、I/Oデバイスからの外部入力に依存することもできません。ウィキペディア

Fooただし、クラスを可変にすると、見かけの不純物はなくなります。

case class Foo(bar:String) {
    private var mutable:Int = 1
    def setFoo(x:Int) = mutable = x
    def foo = mutable
}

Fooクラスの可変性により、getFoo不純になります。

scala> FooContainer.getFoo("test").foo
res5: Int = 1

scala> FooContainer.getFoo("bla").setFoo(5)

scala> FooContainer.getFoo("bla").foo
res7: Int = 5

関数が明らかに純粋であるためには、FooContainer.getFoo("bla").foo常に同じ値を返す必要があります。したがって、記述された構成の「純度」はせいぜい壊れやすいものです。

于 2013-03-12T11:39:30.047 に答える
1

原則として、変更可能なタイプを保持するvarよりも、更新時に置き換えられる不変のコレクションタイプを保持する方が適切ですval。前者は、作成後に変更される可能性のある値を処理することはありません(進化する値自体を保持するクラスを除く)。次に、が保持する更新された値がいつ公開されるかについて適度に注意する必要がありますが、参照の更新は一般にアトミックであるため(32ビットマシンにまたはをRAMにvar格納するなどを除く)、リスクはほとんどありません。 。longdouble

于 2013-03-12T16:39:34.197 に答える