The question Scala asks
Every time you create a name in Scala you choose between two keywords, and the choice answers one question: will this value ever change?
valdeclares a read-only name. It is assigned once, and the compiler refuses any later assignment.vardeclares a variable. Its value can be replaced as often as needed.
Because a val never changes, you can read the code with less effort: wherever you see the name, it has the same value it was given at the start. That is why Scala code uses val by default and var only where a value truly changes, such as a counter, a running total or a position that moves.
val pi = 3.14159
var lives = 3
lives -= 1
println(s"lives = $lives")
lives = 2
There are no type annotations here. Scala infers Double for pi and Int for lives from the values. The s before the quotes makes the string an interpolator, so $lives is replaced by the current value. Without the s, the output would contain the characters $lives.
What happens when you reassign a val
This is the mistake the lesson wants you to recognise:
val maxLives = 3
maxLives = 5
-- [E052] Type Error ------------------------------------------------------
| maxLives = 5
| ^^^^^^^^^^^^
| Reassignment to val maxLives
The carets underline the assignment that broke the rule, and the message names the culprit. There are two honest fixes: stop reassigning and keep the val, or change the declaration to var because the value must change.
Compound operators are assignments too
The operator += reads the variable, adds to it and stores the result, so it is also a reassignment. On a val that holds an Int it fails as well, although the compiler's wording differs. Scala first looks for a += method on Int, doesn't find one, and reports:
| maxLives += 1
| ^^^^^^^^^^^^^
| value += is not a member of Int
Either way, the cure is the same: a value that gets updated must be a var.
The exercise step by step
The program sets up a tiny game: a fixed number of lives and a changing score. The expected output is two lines, maxLives = 3 and score = 15.
- Declare the constant.
val maxLives = 3. The rules of the game never change, sovalis right, and Scala infersInt. - Print it.
println(s"maxLives = $maxLives"). Read-only means you can't change the value, but you can read it as often as you like. - Declare the score.
var score = 0. A running total has to change, andvarallows it. - Add the first points.
score += 10is short forscore = score + 10. It compiles only becausescoreis avar. - Add the bonus.
score += 5works the same way and starts from the 10 stored by the previous line. - Print the total. Another interpolated string shows
score = 15.
The solution in Scala
val maxLives = 3
println(s"maxLives = $maxLives")
var score = 0
score += 10
score += 5
println(s"score = $score")
The output is:
maxLives = 3
score = 15
Notice what each keyword allows. maxLives stays at 3 from the first line to the last. score goes from 0 to 10 to 15, one assignment at a time.
Immutability beyond val
A val stops you from re-pointing a name, but the object behind it may still be changeable. A val holding an ArrayBuffer can't be assigned a different buffer, yet buf += 3 adds an element to the same one. The standard immutable collections, such as List, Vector and Map, can't be changed at all, so combining val with them gives the strongest guarantee.
Common mistakes
- Declaring the score with
val. The first+=then fails to compile. The error points at the update line, not the declaration, so read it back to the keyword. - Declaring everything with
var. It compiles, but it throws away the guarantee that makesvaluseful. Start withval, and change it only when the compiler tells you a value needs to change. - Forgetting the
s.println("maxLives = $maxLives")prints the literal textmaxLives = $maxLives. - Redeclaring instead of updating. Writing
var score = 10a second time doesn't update the first variable. The compiler rejects it because the name is already defined.
Key takeaways
valis assigned once,varcan be reassigned.- Reassigning a
valis a compile error:Reassignment to val. - Updates such as
+=need avar. - Prefer
valand usevarwhen a value must change.
