Pattern Matching Gotcha

Pattern matching construct in Scala is powerful. It allows you to easily assign values to local variables, match against literal values, and deconstruct a more complex type into component parts. Most of the time this ends up being very intuitive. Here are a few trivial examples:

List(1, 2, 3, 4) match {
  case head :: tail => "head is 1, tail is List(2, 3, 4)"
}

List(1, 2, 3, 4) match {
  case head :: Nil => "fail" // Won't match, because Nil != List(2, 3, 4)
}

case class Person(name: String, age: Int)
val p = Person("Bob", 30)
p match {
  case Person(n, a) => "n == Bob; a == 30" // local variable name doesn't matter
  case Person("Sally", age) => "Matches when name == Sally; age doesn't matter"
}

42 match {
  case x => "Matches anything, refer to it using x"
  case _ => "Matches anything, can't refer to matched thing"
}

42 match {
  case 1 => "no match"
  case 42 => "yup, literal match"
}

So what’s the gotcha? A local variable in the match scope will shadow a variable that starts with a lowercase letter. This is different than a variable that starts with an uppercase letter.

val foo = "foo"
val BigFoo = "foo"
"bar" match {
  case "foo" => "this does not match, which is expected"
  case BigFoo => "this does not match, which is expected; it behaves the same way as matching against the string literal"
  case foo => "this *does* match! you probably didn't expect that"
}

The last case shows this behavior in action.