val and var
Scala has two ways to name a value. val creates an immutable binding — once assigned, it can never point at anything else. var creates a mutable variable you can reassign. Idiomatic Scala uses val almost everywhere and reaches for var only for a local counter or accumulator, because code where names never change is easier to read, test and run in parallel.
@main def run(): Unit =
val name = "Asha"
var visits = 1
println(s"$name has visited $visits time")
visits = visits + 1
visits += 1
println(s"$name has visited $visits times")Asha has visited 1 time
Asha has visited 3 timesTry adding name = "Ravi" after the first println and read the compiler error — then undo it.
Reassignment to val
@main def run(): Unit =
val score = 10
score = 20
println(score)-- [E052] Type Error: Main.scala:3:8
3 | score = 20
| ^^^^^^^^^^
| Reassignment to val score
1 error found
Compilation failedscore was declared with val, so the compiler forbids pointing it at a new value. This is caught before the program ever runs.
If the value genuinely changes, declare it with var. More often the better fix is a new name: val finalScore = score + 10.
@main def run(): Unit =
var score = 10
score = 20
println(score)val fixes the name, not the object. val buf = scala.collection.mutable.ArrayBuffer(1) can still have items appended; you just cannot make buf point at a different buffer. Real immutability comes from immutable types like List and case classes — Module 06 covers the difference.There is also lazy val: its right-hand side is not evaluated until the first time the value is used, and then the result is cached.
@main def run(): Unit =
lazy val config =
println("loading config...")
"prod"
println("program started")
println(config)
println(config)program started
loading config...
prod
prodThe body ran once, at the first use — not at the declaration, and not again on the second use.
