Scala Variables

Every program needs a way to store data. In Scala, you store data using val and var. These two keywords look similar but behave very differently. Choosing the right one matters for writing safe, predictable programs.

val — Immutable Values

A val stores a value that you set once and never change. Once assigned, it is locked. Attempting to reassign it causes a compiler error.

val country = "India"
val temperature = 36.5
val isRaining = false

country = "Brazil"   // Error: Reassignment to val

Think of val like a name badge at a conference. Once printed, it stays the same all day. You cannot cross it out and write a new name mid-conference.

var — Mutable Variables

A var stores a value that you can replace at any time. It is like a whiteboard — you write on it, erase it, and write something new.

var score = 0
println(score)   // 0

score = 10
println(score)   // 10

score = score + 5
println(score)   // 15

val vs var Comparison


┌─────────────────────┬──────────────────────────┬───────────────────────┐
│ Feature             │ val                      │ var                   │
├─────────────────────┼──────────────────────────┼───────────────────────┤
│ Reassignable?       │ No                       │ Yes                   │
│ Like a...           │ Constant / ink-written   │ Pencil-written value  │
│ Thread-safe?        │ Yes (safer)              │ Needs care            │
│ Preferred in Scala? │ Yes                      │ Only when needed      │
└─────────────────────┴──────────────────────────┴───────────────────────┘

Why Prefer val?

Scala's community and documentation strongly recommend using val by default. Immutable values are easier to reason about. When a value never changes, you never have to ask "what is this value right now?" — you always know. Programs built on immutable values also work more safely in concurrent (multi-threaded) environments.

Use var only when the data genuinely needs to change over time, like a running total or a counter in a loop.

Type Declarations

Scala infers types automatically, but you can also declare them explicitly:

// Type inferred by Scala
val city = "Tokyo"        // Scala sees it is a String

// Type declared explicitly
val city: String = "Tokyo"

// More examples with explicit types
val age: Int = 25
val height: Double = 5.9
val active: Boolean = true
val initial: Char = 'A'

Both styles work. Explicit types are useful for documentation — they make the intent of a variable obvious to anyone reading the code later.

Scala's Core Data Types for Variables


Type        │ What it holds              │ Example
────────────┼────────────────────────────┼────────────────
Int         │ Whole numbers              │ val n: Int = 42
Double      │ Decimal numbers            │ val d: Double = 3.14
Boolean     │ true or false              │ val b: Boolean = true
String      │ Text                       │ val s: String = "hello"
Char        │ Single character           │ val c: Char = 'Z'
Long        │ Very large whole numbers   │ val l: Long = 9999999999L
Float       │ Smaller decimal numbers    │ val f: Float = 1.5f

Declaring Multiple Values

val firstName = "Ravi"
val lastName  = "Kumar"
val fullName  = firstName + " " + lastName

println(fullName)   // Ravi Kumar

Lazy Values

A lazy val delays computation until the value is actually used. The calculation runs only once — the first time you access it — and the result gets stored for future accesses.

lazy val expensiveResult = {
  println("Computing now...")
  100 * 200
}

println("Before access")
println(expensiveResult)   // "Computing now..." prints here
println(expensiveResult)   // uses stored result, no recomputation

Output:

Before access
Computing now...
20000
20000

Use lazy val when the computation is expensive and you might not always need the result. It is like ordering food only when you are actually hungry, rather than ordering everything on the menu upfront.

Variable Naming Rules

Scala follows specific naming conventions:

// VALID names
val myAge = 25
val totalScore = 100
val isLoggedIn = true
val MAX_SIZE = 1000     // constants sometimes use ALL_CAPS

// INVALID names
val 1stPlace = "Gold"  // cannot start with a digit
val my-age = 25        // hyphens not allowed
val class = "English"  // 'class' is a reserved keyword

By convention, Scala uses camelCase for variable and function names: firstName, userScore, isActive. Class names use PascalCase: UserAccount, OrderItem.

Block Scope

Variables exist only within the block where you define them. A block is any section of code inside curly braces {} — or, in Scala 3, the indented block under a function or expression.

@main def scopeDemo(): Unit =
  val outer = "I exist everywhere in this function"

  if true then
    val inner = "I only exist inside this if block"
    println(inner)   // works fine

  println(outer)    // works fine
  println(inner)    // Error: inner is not in scope here

Think of scope like rooms in a house. Items stored in the bedroom (inner scope) are not available in the living room (outer scope). Items in the living room are accessible from the bedroom.

Updating a var with Compound Operations

var counter = 0

counter += 1     // same as counter = counter + 1
counter += 1
counter += 1

println(counter)   // 3

var total = 100
total -= 20        // 80
total *= 2         // 160
total /= 4         // 40

println(total)     // 40

Scala supports +=, -=, *=, and /= for compact updates to var values. Note: these operators do not work on val.

Constants as Object Members

For application-wide constants, define val inside an object:

object Config:
  val maxRetries = 3
  val timeout    = 30
  val appName    = "StudyApp"

@main def run(): Unit =
  println(Config.appName)    // StudyApp
  println(Config.maxRetries) // 3

This pattern keeps constants organized and prevents name collisions across large codebases.

Leave a Comment

Your email address will not be published. Required fields are marked *