scalascala-2.8

Scala pattern matching with lowercase variable name


I found that when using pattern matching with alternatives (for strings), Scala accepts variables starting with upper case (in the example below, MyValue1 and MyValue2), but not those starting with lower case (myValue1, myValue2). Is this a bug or a feature of Scala? I get this in version 2.8. If this is a feature, can anyone explain the rationale behind it? This is the code I used:

val myValue1 = "hello"
val myValue2 = "world"
val MyValue1 = "hello"
val MyValue2 = "world"

var x:String = "test"

x match {
  case MyValue1 | MyValue2 => println ("first match")
  case myValue1 | myValue2 => println ("second match")
}

On running, I get the following:

scala> val myValue1 = "hello"
myValue1: java.lang.String = hello

scala> val myValue2 = "world"
myValue2: java.lang.String = world

scala> val MyValue1 = "hello"
MyValue1: java.lang.String = hello

scala> val MyValue2 = "world"
MyValue2: java.lang.String = world

scala> var x:String = "test"
x: String = test

scala> x match {
 |   case MyValue1 | MyValue2 => println ("first match")
 |   case myValue1 | myValue2 => println ("second match")
 | }
<console>:11: error: illegal variable in pattern alternative
     case myValue1 | myValue2 => println ("second match")
          ^
<console>:11: error: illegal variable in pattern alternative
     case myValue1 | myValue2 => println ("second match")
                     ^

EDIT:

So it is indeed a feature and not a bug... Can anyone provide an example when this might be useful?

When I use:

x match {
   case myValue1 => println ("match")
   case _ => 
}

I get an unreachable code warning on the last case, implying that the first one always matches.


Solution

  • This is not specific to patterns with alternatives, and it is not a bug. An identifier that begins with a lowercase letter in a pattern represents a new variable that will be bound if the pattern matches.

    So, your example is equivalent to writing:

    x match {
       case MyValue1 | MyValue2 => println ("first match")
       case y | z => println ("second match")
    }
    

    You can work around this by using backticks:

    x match {
       case MyValue1 | MyValue2 => println ("first match")
       case `myValue1` | `myValue2` => println ("second match")
    }