10.6. Understanding Mutable Variables with Immutable Collections

Problem

You may have seen that mixing a mutable variable (var) with an immutable collection causes surprising behavior. For instance, when you create an immutable Vector as a var, it appears you can somehow add new elements to it:

scala> var sisters = Vector("Melinda")
sisters: collection.immutable.Vector[String] = Vector(Melinda)

scala> sisters = sisters :+ "Melissa"
sisters: collection.immutable.Vector[String] = Vector(Melinda, Melissa)

scala> sisters = sisters :+ "Marisa"
sisters: collection.immutable.Vector[String] = Vector(Melinda, Melissa, Marisa)

scala> sisters.foreach(println)
Melinda
Melissa
Marisa

How can this be?

Solution

Though it looks like you’re mutating an immutable collection, what’s really happening is that the sisters variable points to a new collection each time you use the :+ method. The sisters variable is mutable—like a non-final field in Java—so it’s actually being reassigned to a new collection during each step. The end result is similar to these lines of code:

var sisters = Vector("Melinda")
sisters = Vector("Melinda", "Melissa")
sisters = Vector("Melinda", "Melissa", "Marisa")

In the second and third lines of code, the sisters reference has been changed to point to a new collection.

You can demonstrate that the vector itself is immutable. Attempting to mutate one of its elements—which doesn’t involve reassigning the variable—results in an error:

scala> sisters(0) = "Molly" <console>:12: error: value ...

Get Scala Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.