3

Scala が不変性を完全に受け入れていることは理解しています。

今、クラスなどで(変数を介して)何らかの状態を保持する必要があるというシナリオを考えています。これらの変数は後で更新する必要があります。後でクラスに戻って、更新された変数にアクセスできます。

非常に単純な例を 1 つ使用して、簡単に説明します。

class A {
  var x: Int
  def compute: Int = {calling some other processes or such using x as input}
}

……

def invoker() {
  val a: A = new A
  a.x = 1
  ......
  val res1 = a.compute
  a.x = 5
  ......
  val res2 = a.compute
  ......
}

ご覧のとおり、x を変更し続けて結果を取得する必要があります。次のような計算の引数として x を単純に保持できると主張する場合

def compute(x: Int) 
......

それは良い考えですが、x の設定値と結果の計算を完全に分離する必要があるため、私の場合はできません。言い換えれば、x 値を設定しても「計算」が開始されるべきではありません。むしろ、プログラム内でいつでも x 値を設定でき、必要なときにプログラム内で計算のために値を再利用できる必要があります。 .

この場合、変数 (var x: Int) を使用しています。これは正当なものですか、それとも不変の処理方法がまだありますか?

4

5 に答える 5

0

状態を保存するときはいつでも、可変性を使用する必要があります。

あなたの場合、xを保存して別々に計算したいと考えています。本質的に、これは状態が必要であることを意味します。これは、計算の結果がxの状態に依存するためです。

computeを含むクラスを本当に不変にしたい場合は、他の可変クラスにxを含める必要があり、それを compute メソッドに渡す必要があります。

于 2013-05-30T21:19:03.827 に答える
0

不変の A クラス (ここではケース クラス) を作成し、オブジェクトに可変性を処理させます。状態が変化するたびに、新しい A オブジェクトを作成し、オブジェクト内の参照を変更します。これは、別のスレッドから x を設定すると、並行処理が少し良くなります。変数を volatile または AtomicReference にするだけで済みます。

object A {
    private[this] var a = A(0)
    def setX(x: Int) { if (x != a.x) a = new A(x) }
    def getA: A = a
}

case class A(x: Int) {
    def compute: Int = { /*do your stuff*/ }
}
于 2013-05-31T17:36:58.827 に答える
0

あなたのパターンはListBuffer、たとえば(関数sizeとして)使用されます。compute

そうです、正当な理由でこのパターンを使用できる場合があるかもしれません。例:

val l = List(1, 2, 3)

val lb = new ListBuffer[Int]
l.foreach(n => lb += n * n)
val result = lb.toList

println(result)

一方、バッファは通常、不変のインスタンスをできるだけ早く作成するためにのみ使用されます。このコードを見ると、変更可能であることを示す可能性のある項目が 2 つあります: 可変バッファとforeach(foreach副作用のためにのみ呼び出されるため)

したがって、別のオプションは

val l = List(1, 2, 3)

val result = l.map(n => n * n)

println(result)

より少ない行で同じことを行います。あなたは不変のインスタンスと「機能的な」関数を見ているだけなので、私はこのスタイルを好みます。

抽象的な例では、可変状態と関数を分離しようとすることができます。

class X(var i: Int)

class A {
  def compute(x: X): Int = { ... }
}

おそらくさえ

class X(val i: Int)

この方法computeは機能的になります。戻り値はパラメーターにのみ依存します。

「予期しない」不変クラスに関する私の個人的なお気に入りはscala.collection.immutable.Queue. 「命令型」のバックグラウンドでは、キューが不変であるとは期待できません。

したがって、パターンを見ると、それを不変に変更できる可能性があります。

于 2013-05-31T07:07:31.447 に答える
0

むしろ、プログラム内でいつでも x 値を設定でき、必要なときにプログラム内でいつでも計算のために値を再利用できる必要があります。

次に、定義により、クラスをステートフルにする必要があります。特定のクラスが状態を必要としないように問題を再構築することはできますが、それが有用であるか、および/または手間をかける価値があるかどうかは、理解する必要があります。

于 2013-05-30T21:45:58.077 に答える
0

関数型プログラミングをさらに数か月行った後、ここに私の再考があります。

変数が変更/変更/更新/変更されるたびに、これを処理する必須の方法は、その変数でそのような変更を正しく記録することです。機能的な考え方は、(変化を引き起こす) 活動があなたに新しい状態をもたらすようにすることです。つまり、因果関係のようなものです。機能的思考法は、原因と結果の間の移行活動に焦点を当てています。

以上のことから、プログラム実行の任意の時点で、私たちの成果は中間結果です。どのように行っても、結果を保持する場所が必要です。そのような中間結果は状態であり、はい、それを保持するための変数が必要です。それが私が抽象的な思考だけで共有したいことです。

于 2013-11-12T18:58:56.520 に答える