Immutable vs mutable collections
Scala ships two families of collections. The immutable ones — List, Vector, Set, Map — are what you get by default, with no import. An immutable collection never changes: "adding" an element returns a new collection and leaves the old one exactly as it was. The mutable ones live in scala.collection.mutable — ArrayBuffer, ListBuffer, mutable.Map, mutable.Set — and change in place.
import scala.collection.mutable
@main def run(): Unit =
val nums = List(1, 2, 3)
val more = nums :+ 4
println(nums)
println(more)
val buf = mutable.ArrayBuffer(1, 2, 3)
buf += 4
buf(0) = 100
println(buf)
val frozen = buf.toList
buf.clear()
println(frozen)
println(buf)List(1, 2, 3)
List(1, 2, 3, 4)
ArrayBuffer(100, 2, 3, 4)
List(100, 2, 3, 4)
ArrayBuffer()nums is untouched by :+. The buffer changes in place, and toList takes an immutable snapshot that survives clear(). Import the package, not the classes, and write mutable.ArrayBuffer: the prefix tells every reader "this one changes".
Create a mutable.ListBuffer[String], append three names with +=, then print buf.toList.reverse.
Trying to change an element of an immutable List
@main def run(): Unit =
val scores = List(10, 20, 30)
scores(0) = 99
println(scores)-- [E008] Not Found Error: Main.scala:3:2
3 | scores(0) = 99
| ^^^^^^
| value update is not a member of List[Int] - did you mean scores.updated?
1 error found
Compilation failedxs(i) = v is shorthand for xs.update(i, v), a method only mutable collections have. List has no update — and the compiler even points you at the immutable alternative, updated, which returns a new list.
Use updated and keep the result, or switch to a mutable buffer if you really need in-place change.
@main def run(): Unit =
val scores = List(10, 20, 30)
val fixedScores = scores.updated(0, 99)
println(fixedScores)0 :: nums reuses every cell of nums. Teams reach for mutable collections inside one function for speed, then return an immutable result.