Skip to content

Scala Pattern Matching

Pattern matching is one of Scala’s most powerful and frequently used features. It allows you to check a value against a series of patterns and execute corresponding code blocks, simplifying complex conditional logic, especially when dealing with structured data.

A pattern match expression starts with a value followed by the match keyword and a block containing case clauses. Each case defines a pattern and an expression (=> expression) to execute if the value matches the pattern. The first matching pattern’s expression is evaluated.

Here’s a simple example matching an integer:

@main def PatternMatchDemo(): Unit = {
def describe(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case n if n > 2 && n < 10 => s"a small number ($n)" // Pattern guard
case _ => "something else" // Wildcard pattern
}
println(describe(1))
println(describe(5))
println(describe(100))
}

Output:

one
a small number (5)
something else

Key elements in the example:

  • case 1 => ...: Matches the literal value 1.
  • case n if n > 2 ...: Matches any integer, binds it to n, and applies a guard condition (if).
  • case _ => ...: The wildcard _ matches anything not caught by previous cases. It’s crucial for exhaustiveness.

You can also match based on the type of the value, especially useful with Any:

@main def TypeMatchDemo(): Unit = {
def matchType(x: Any): String = x match {
case i: Int => s"It's an Integer: $i"
case s: String => s"It's a String: $s"
case d: Double => s"It's a Double: $d"
case _: List[_] => "It's a List of something"
case _ => "It's something else"
}
println(matchType(42))
println(matchType("Hello Scala"))
println(matchType(3.14))
println(matchType(List(1, 2, 3)))
println(matchType(true))
}

Output:

It's an Integer: 42
It's a String: Hello Scala
It's a Double: 3.14
It's a List of something
It's something else

The pattern s: String checks if x is a String and, if so, binds it to the variable s of type String.

Case classes are specifically designed to work seamlessly with pattern matching. They automatically provide companion objects with apply and unapply methods, making construction and deconstruction easy.

// Define a case class
case class Person(name: String, age: Int)
@main def CaseClassMatchDemo(): Unit = {
val alice = Person("Alice", 30)
val bob = Person("Bob", 25)
val charlie = Person("Charlie", 30)
for (person <- List(alice, bob, charlie)) {
person match {
case Person("Alice", 30) => println(s"Hi Alice!")
case Person("Bob", age) => println(s"Hi Bob! You are $age years old.")
case Person(name, 30) => println(s"Hi $name! You are 30.")
case Person(name, age) => println(s"Who are you, $name of age $age?")
}
}
}

Output:

Hi Alice!
Hi Bob! You are 25 years old.
Hi Charlie! You are 30.

Benefits of case class:

  1. Immutable fields by default (constructor arguments become val fields).
  2. Automatic implementation of equals, hashCode, and toString based on constructor arguments.
  3. Automatic apply method (e.g., Person("Alice", 30) instead of new Person(...)).
  4. Automatic unapply method, enabling easy deconstruction in pattern matching (e.g., case Person(name, age) => ...).

Pattern matching is used extensively in Scala for tasks like: processing messages in actor systems (like Akka), handling optional values (Option), processing results (Try or Either), deconstructing complex data structures (like JSON or XML trees), and implementing state machines.

Explore matching on collections (like List(1, 2, _*)), Option (Some(v) vs None), and using extractors (unapply methods) for custom pattern matching logic. Check the official Scala documentation for more advanced patterns.