100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

vals, vars, and Types

How Scala's val/var distinction enforces immutability by default, and how the static type system infers and checks types at compile time.

FoundationsBeginner8 min readJul 10, 2026
Analogies

vals, vars, and Types

Scala gives you two ways to bind a name to a value: val creates an immutable binding that can be assigned exactly once, while var creates a mutable binding that can be reassigned as many times as needed. Scala is also statically typed, meaning every val or var has a fixed type determined at compile time — either written explicitly or inferred automatically from the initializer — and idiomatic Scala code favors val by default, reserving var for the relatively rare cases where genuine mutation is required.

🏏

Cricket analogy: Choosing val over var in Scala is like a captain locking in a batting order before the toss rather than shuffling it mid-innings — once declared, a val binding, like Rohit Sharma opening every single match, cannot be swapped out later in the same scope.

Immutability with val

It's important to distinguish reference immutability from object immutability: a val guarantees the binding itself can never point to a different object, but if that object is an inherently mutable data structure — such as a scala.collection.mutable.ArrayBuffer — its internal contents can still change through its own methods. This is different from truly immutable data (like a List or a case class with only vals), which cannot be changed at all once constructed, regardless of how the reference to it is held.

🏏

Cricket analogy: A val referencing a mutable ArrayBuffer is like a fixed playing XI announced for the match (the val — you can't swap the list itself) even though individual players' batting stats (the buffer's contents) keep updating ball by ball during the innings.

Mutability with var

var is best reserved for narrowly scoped, genuinely mutable state — a loop counter, a running accumulator inside a tight block — rather than being sprinkled throughout a codebase. Widespread use of var makes programs harder to reason about, because the value at any point depends on execution history rather than being a fixed fact, and it also introduces real risk under concurrency, since two threads reassigning the same var without synchronization can produce race conditions.

🏏

Cricket analogy: Using var for a running total, like a var runs = 0 updated after every ball, is like a scoreboard operator manually updating the total after each delivery — necessary and legitimate, but if every single statistic on the ground were mutable and shared, chaos and scoring errors would follow, which is why Scala encourages minimizing var usage.

Type Inference and Explicit Typing

Scala's type inference lets you write val count = 10 and have the compiler deduce Int without any annotation, similarly inferring Double from 19.99, Boolean from true, and String from a quoted literal. Inference is a convenience, not a loosening of the type system — the inferred type is checked at compile time exactly as if you had written it — and best practice is to still write explicit type annotations on public method signatures so the contract is documented and doesn't silently change if the implementation is refactored.

🏏

Cricket analogy: Scala's type inference determining val runs = 42 is an Int without you writing Int is like an experienced umpire instantly recognizing a delivery as a no-ball from the bowler's front foot alone, without needing it spelled out — but for a public API, explicitly stating the type is like formally declaring a review decision on the big screen so everyone, including future teammates reading your code, is unambiguously clear.

scala
// Immutable binding — cannot be reassigned
val language: String = "Scala"
// language = "Java"  // Compile error: reassignment to val

// Mutable binding — can be reassigned
var attempts: Int = 0
attempts = attempts + 1   // OK
attempts += 1             // OK, same effect

// Type inference: the compiler infers Int, Double, Boolean, String
val count = 10            // Int
val price = 19.99         // Double
val isActive = true       // Boolean
val name = "Ada Lovelace" // String

// Explicit typing, recommended for public API signatures
def computeArea(radius: Double): Double = math.Pi * radius * radius

// val referencing a mutable collection: the reference is fixed,
// but the collection's contents can still change
import scala.collection.mutable.ArrayBuffer
val scores: ArrayBuffer[Int] = ArrayBuffer(10, 20, 30)
scores += 40  // legal: mutates the buffer's contents, not the val binding

Scala's type inference means you rarely need to write val count: Int = 10 — the compiler determines Int from the literal on the right-hand side. This removes a lot of the boilerplate common in older Java code while keeping the full safety of a statically typed language, since the inferred type is checked at compile time just as if you'd written it explicitly.

Attempting to reassign a val (e.g. language = "Kotlin" after val language = "Scala") is a compile-time error, not a runtime one — this is a deliberate safety feature. Also be wary of overusing var: idiomatic Scala favors immutability by default, and code with many mutable variables is harder to reason about and more prone to concurrency bugs.

  • val creates an immutable binding — it can be assigned once and never reassigned.
  • var creates a mutable binding that can be reassigned as many times as needed.
  • A val bound to a mutable object (like an ArrayBuffer) still allows the object's internal contents to change; only the reference is fixed.
  • Scala infers types automatically from initializer expressions, but explicit type annotations are recommended on public method signatures.
  • Common built-in types include Int, Double, Boolean, String, and Char.
  • Idiomatic Scala favors val over var to make code easier to reason about and safer under concurrency.
  • Reassigning a val is a compile-time error, catching mistakes before the program ever runs.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#ScalaStudyNotes#ValsVarsAndTypes#Vals#Vars#Types#Immutability#StudyNotes#SkillVeris#ExamPrep