Scala
01 / 02

Syntax, Case Classes & Pattern Matching

Syntax, Case Classes & Pattern Matching

Basics

val name: String = "Alice"   // immutable — reassignment is a compile error
var counter: Int = 0          // mutable — favor val, reach for var only when needed

def add(a: Int, b: Int): Int = a + b

s"Hello, $name! You are ${counter + 1}."  // string interpolation

// Option — the idiomatic null-free way to represent absence
val maybeUser: Option[User] = users.find(_.id == id)
maybeUser match {
  case Some(user) => println(user.name)
  case None       => println("not found")
}
maybeUser.map(_.name).getOrElse("unknown")

Case Classes & Immutable Updates

case class User(name: String, age: Int, email: String)

val alice = User("Alice", 30, "alice@example.com")
val olderAlice = alice.copy(age = 31)  // NEW instance — original stays unchanged

alice == User("Alice", 30, "alice@example.com")  // true — compared by value, not reference

// sealed trait + case classes — exhaustive, compiler-checked pattern matching
sealed trait Shape
case class Circle(radius: Double) extends Shape
case class Rectangle(width: Double, height: Double) extends Shape

def area(shape: Shape): Double = shape match {
  case Circle(r) => math.Pi * r * r
  case Rectangle(w, h) => w * h
  // adding a new Shape subtype and forgetting a case here triggers a
  // compiler warning/error — this is the "expression problem" solved

Collections & Higher-Order Functions

val numbers = List(1, 2, 3, 4, 5)

numbers.map(_ * 2)               // List(2, 4, 6, 8, 10)
numbers.filter(_ % 2 == 0)       // List(2, 4)
numbers.reduce(_ + _)            // 15

// flatMap flattens the result — map alone would nest it
List(1, 2).flatMap(n => List(n, n * 10))  // List(1, 10, 2, 20)

// for comprehension — sugar over map/flatMap/filter, short-circuits on None
for {
  a <- Some(3)
  b <- Some(4)
} yield a + b   // Some(7) — if EITHER were None, the whole result is None

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free