Why this val can be reassigned

scala> val x = ArrayBuffer(1,2,3,4)
val x: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)

scala> x += 5
val res19: x.type = ArrayBuffer(1, 2, 3, 4, 5)

The “+=” symbol is a reassignment operator, am i right?
so x was reassigned. I am a bit confused about this.

x itself is a constant pointer to an ArrayBuffer. But ArrayBuffer is mutable. += isn’t changing x, it’s changing the thing that x is pointing to.

(It’s a common point of confusion: val just means that you can’t change the pointer, but it has nothing to do with whether the thing being pointed to is mutable or immutable. The world is much simpler if you just avoid mutable types entirely.)

1 Like

+= is a method on ArrayBuffer. So x += 5 is x.+=(5), which adds an element to the (existing, non-reassigned) ArrayBuffer.

However, to ease the transition between mutable and immutable operations, Scala will rewrite a += b to a = a + b if the += method does not exist. In that way, if a is immutable, but has a + method, you can construct a new thing, a + b and assign it back to the variable a, assuming that a is a var.

So whether you have val x = ArrayBuffer(1, 2) or var x = Set(1, 2), you can write x += 3. But what that actually means differs between the two cases; it’s only the syntactic sugar of the += to = + rewrite that makes them look the same.

2 Likes
scala> var y = 1
var y: Int = 1

scala> y += 1

scala> y
val res3: Int = 2

scala> val x = ArrayBuffer(1,2,3)
val x: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)

scala> x += 4
val res4: x.type = ArrayBuffer(1, 2, 3, 4)

As you see, the first += is the reassignment. But the second is not.
So this is somewhat confused. :slight_smile:

Thanks

It’s not confused–confusing maybe, but not confused.

There’s a very simple rewrite rule. If a has a method +=, then a += b calls the method. If not, but it has a + method, and a is a var, then a += b means a = a.+(b).

(Actually, it works for any operator ending in =…it will try the method-plus-assignment variant.)