1

次の点を考慮してください。

scala> val myset = Set(1,2)
myset: scala.collection.immutable.Set[Int] = Set(1, 2)

scala> myset += 3
<console>:9: error: reassignment to val
              myset += 3
                    ^

scala> var myset = Set(1,2)
myset: scala.collection.immutable.Set[Int] = Set(1, 2)

scala> myset += 3

scala> myset
res47: scala.collection.immutable.Set[Int] = Set(1, 2, 3)

「alex」を追加できる場合もあれば、追加できない場合もあります。val と var の違いを知っています。ただし、両方のケースで私を混乱させたのは、Scala が Set は不変であるが、異なる動作を許可することを教えてくれます。

oncase myset は val であり、1 つは var であるため、私はそうしたくありません。どちらの場合も、Scala は myset が不変セットであると言いながら、両方を異なる方法で扱う理由を説明するために、それよりも深い答えが必要です。直感に反するからです。

たとえば、可変セットを使用し、不変セットを var として宣言することに違いはありますか? では、なぜ scala はルールを曲げることができるのでしょうか? 不変と言われたら、それはそれを意味するのではないでしょうか?

ありがとう。

4

3 に答える 3

3

まず、+=呼び出しを翻訳しましょう

val myset = Set(1,2)
myset = myset + 3 //this is what the compiler does for myset += 3

これは、実際に+on というメソッドを呼び出していることを意味しSet、そのscaladocは次のように述べています。

要素が既に存在しない限り、追加の要素で新しいセットを作成します。

したがって、コードがしようとしているのは、追加された要素で新しいを作成し、それを 不変の参照に再割り当てすることです。Set myset

ここで、( を使用して) 参照を変更可能なものに変更すると、新しく作成された不変varのもので再割り当てできます。 Set(1,2,3)

元の Set(1, 2) は依然として不変であり、規則に違反していません。これを事例で説明しましょう

var myset = Set(1,2)
val holdIt = Some(myset)
myset += 3
println(myset) // will print Set(1, 2, 3)
println(holdIt)// will print Some(Set(1, 2))

ご覧のとおり、Setによってキャプチャされた元のOptionは変更されていません。新しく作成された への変数参照を再割り当てしただけです。Set

于 2013-02-09T11:57:21.683 に答える
2

不変の Set を使用すると、新しい Set が作成され、 に再割り当てされます。varこれは、 を使用する場合には不可能valです。ただし、変更可能な Set は変更できます。以下は完全に保存されたデモではありませんが、不変の Set を使用して新しいオブジェクトが作成され、可変の Set インスタンスが同じままであることを示しています。

scala> var set1 = Set(1, 2)
set1: scala.collection.immutable.Set[Int] = Set(1, 2)

scala> System.identityHashCode(set1)
res0: Int = 2119337193

scala> set1 += 3

scala> System.identityHashCode(set1)
res2: Int = 1866831260

scala> var set2 = collection.mutable.Set(1, 2)
set2: scala.collection.mutable.Set[Int] = Set(2, 1)

scala> System.identityHashCode(set2)
res3: Int = 594308521

scala> set2 += 3
res4: scala.collection.mutable.Set[Int] = Set(2, 1, 3)

scala> System.identityHashCode(set2)
res5: Int = 594308521
于 2013-02-09T12:00:26.710 に答える
2

mysetポインターと Set(1,2)オブジェクトとして考える

ポインターが一度だけ割り当てられ、val myset別のオブジェクトを指すことはできません (つまり、ポインターは不変です) の場合は、var myset任意の回数を割り当てることができ、別のオブジェクトを指すことができます (つまり、ポインターは変更可能です) 。

どちらの場合も、オブジェクトSet(1,2)は不変です。

あなたがするとき

scala> val myset = Set(1,2)
myset: scala.collection.immutable.Set[Int] = Set(1, 2)

scala> myset += 3
<console>:9: error: reassignment to val
              myset += 3
                    ^

myset += 3 実際には、それSet3追加された新しいものを提供します..

ポインターは不変であるため、メソッドによって返されmysetた新しいものに再割り当てすることはできません。object+

の場合のように

scala> var myset = Set(1,2)
myset: scala.collection.immutable.Set[Int] = Set(1, 2)

scala> myset += 3

ポインターは可変であるため、メソッドによって返されmysetた新しいものに再割り当てできます。object+

于 2013-02-09T12:07:55.593 に答える