I can define a variable (by var
) that is immutable:
var x = scala.collection.immutable.Set("aaaaaa","bbbbbb")
println(x.isInstanceOf[scala.collection.immutable.Set[String]])
x += "cccc"
println(x.isInstanceOf[scala.collection.immutable.Set[String]])
This results in:
true
true
+=
method is not a member of scala.collection.immutable.Set
, so what is happening?
In short, the difference is that a val simply gives a name to some computed value and is read-only, while a var is a memory cell that you can write to (you can "mutate" it) again and again. It's easiest to think of this in terms of objects.
In Scala we can declare a variable using var and val keywords. var keyword is used to create a mutable (read-write) variable and val keyword is used to create an immutable (read only) variable. Syntax – Creating mutable variable var message = "Foo" Here, message is declared using the keyword var.
val is a keyword in Kotlin that allows us to define properties as read-only. Because they are read-only, they cannot be modified. var, on the other hand, is a keyword that can be used to declare properties in Kotlin that are mutable. These properties are not read-only (as with val) and they can be modified at will.
When a value is defined you can rest peacefully with the knowledge that regardless of any other code that is introduced and tries to access it, the "val" will retain its value. By extension, reading and debugging code becomes easier when a "val" assigned at the beginning of a code segment is unchanged through the end of the code.
The compiler looks for x.+= ...
, and if it can't find it, then it tries to transform the statement into x = x + ...
(which only succeeds if x
is a var
, or x
desugars into a call to some update
method). Since immutable.Set
implements a +
operator, and x
is a var
, this succeeds.
The original immutable set is still unchanged.
Continuing Ken's answer, the + has created a new set, appended the new item, and returned the new set, leaving the original set object unchanged. So you could say var y = x; y += "cccc"
and you would have 2 sets instead of 1:
var x = scala.collection.immutable.Set("aaaaaa","bbbbbb")
println(x.isInstanceOf[scala.collection.immutable.Set[String]])
var y = x
y += "cccc"
println(x)
println(y)
println(x.isInstanceOf[scala.collection.immutable.Set[String]])
println(y.isInstanceOf[scala.collection.immutable.Set[String]])
Getting:
> true
> Set(aaaaaa, bbbbbb)
> Set(aaaaaa, bbbbbb, cccc)
> true
> true
You see the data structure itself is still immutable, but because you declared a var
, the assignment is mutable. So it can be repointed to a new object if that is returned. If you change to declaring x
as a val
, then you couldn't reassign it to a new address.
If you had used a mutable set, then x
and y
would point to the same object because the +
call would have appended the existing set rather than returning a new one (being mutable...):
var x = scala.collection.mutable.Set("aaaaaa","bbbbbb")
println(x.isInstanceOf[scala.collection.immutable.Set[String]])
var y = x
y += "cccc"
println(x)
println(y)
Get:
> Set("aaaaaa","bbbbbb","cccc")
> Set("aaaaaa","bbbbbb","cccc")
Voila.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With