The tale of “val” vs “var” in Scala

Immutability is highly encouraged in Scala applications. As a first class into Scala, it often starts with the difference between val and var. In the naive example when the variable is pointing to a primitive data type like Integer, it all seems obvious, but what if the variable is pointing to a more complex data type, such as a class with a mixture of var and val members?

Let’s dive in with a small example walk-through.

val is conveniently called “value”, implying its immutability, whereas var is called “variable”, implying its mutability. This differentiation conveys the message that a val cannot be re-assigned once initialised, while a variable can.

scala> val myVal = 1
myVal: Int = 1
scala> myVal=2
<console>:25: error: reassignment to val
myVal=2
^
scala> var myVar = 1
myVar: Int = 1
scala> myVar=2
myVar: Int = 2

In the example above, we see that we cannot change the value of myVal after it is assigned, while for myVar , it is okay.

How about more complex objects, such as case class? For python folks, case classes are like named tuples in Python, and are easier to use. Case classes are often used to model more complex data structures. For a brief intro, read this.

Say, you have defined a case class Person as follows:

scala> case class Person(id: Int, name: String)
defined class Person

Now you created a val for Alice:

scala> val p = Person(1, "Alice")
p: Person = Person(1,Alice)

As you might expect, you cannot reassign p to a different person, so the following fails.

scala> p = Person(2, "Bob")
<console>:27: error: reassignment to val
p = Person(2, "Bob")

You might wonder, instead of re-assigning to a different object, can I change its field? Let’s try:

scala> p.name = "Bob"
<console>:25: error: reassignment to val
p.name = "Bob"

No, you cannot change its field either, because by default the field of a case class is a val.

Even though it is discouraged, one can actually declare a case class field as var . Let’s define a Person with name as a variable field:

case class Person(id: Int, var name: String)

Note the additional var before the field.

Now we can define Alice again, and try to change its name.

scala> val p2 = Person(1, "Alice")
p2: Person = Person(1,Alice)
scala> p2.name="Bob"
p2.name: String = Bob
scala> p2
res10: Person = Person(1,Bob)

Surprising? Let’s try to sum up what just happened.

In Scala, a val is immutable, meaning it is prohibited to reassign an object once initialised. However, if the object you assigned to your val itself contains var field, those fields are still allowed to change!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store