Scala Pattern Matching
Examples
Simple Pattern Match
This example shows how to match an input against several values:
def f(x: Int): String = x match {
case 1 => "One"
case 2 => "Two"
case _ => "Unknown!"
}
f(2) // "Two"
f(3) // "Unknown!"
Note: _ is the fall through or default case, but it is not required.
def g(x: Int): String = x match {
case 1 => "One"
case 2 => "Two"
}
g(1) // "One"
g(3) // throws a MatchError
To avoid throwing an exception, it is a best functional-programming practice here to handle the default case (case _ =>
With Oneand two defined somewhere else, or passed as function parameters:
val One: Int = 1
val two: Int = 2
They can be matched against in the following way:
def g(x: Int): String = x match {
case One => "One"
case `two` => "Two"
}
Unlike other programming languages as Java for example there is no fall through. If a case block matches an input, it gets executed and the matching is finished. Therefore the least specific case should be the last case block.
def f(x: Int): String = x match {
case _ => "Default"
case 1 => "One"
}
f(5) // "Default"
f(1) // "Default"
Pattern Matching With Stable Identifier
In standard pattern matching, the identifier used will shadow any identifier in the enclosing scope. Sometimes it is necessary to match on the enclosing scope's variable.
The following example function takes a character and a list of tuples and returns a new list of tuples. If the character existed as the first element in one of the tuples, the second element is incremented. If it does not yet exist in the list, a new tuple is created.
def tabulate(char: Char, tab: List[(Char, Int)]): List[(Char, Int)] = tab match {
case Nil => List((char, 1))
case (`char`, count) :: tail => (char, count + 1) :: tail
case head :: tail => head :: tabulate(char, tail)
}
The above demonstrates pattern matching where the method's input, char, is kept 'stable' in the pattern match: that is, if you call tabulate('x', ...), the first case statement would be interpreted as:
case('x', count) => ...
Scala will interpret any variable demarcated with a tick mark as a stable identifier: it will also interpret any variable that starts with a capital letter in the same way.
Pattern Matching on a Seq
To check for a precise number of elements in the collection
def f(ints: Seq[Int]): String = ints match {
case Seq() =>
"The Seq is empty !"
case Seq(first) =>
s"The seq has exactly one element : $first"
case Seq(first, second) =>
s"The seq has exactly two elements : $first, $second"
case s @ Seq(_, _, _) =>
s"s is a Seq of length three and looks like ${s}" // Note individual elements are not
bound to their own names.
case s: Seq[Int] if s.length == 4 =>
s"s is a Seq of Ints of exactly length 4" // Again, individual elements are not bound
to their own names.
case _ =>
"No match was found!"
}