R – Why does the empty string not match as Seq.empty

pattern matchingscalasequence

EDIT: This was an old bug long since fixed in Scala 2.8 and later

During some experimentation around question Pattern matching a String as Seq[Char], I ran across another weird matching phenomenon. Consider the following code that treats a string as a sequence of characters:

def %%&#(input: String) : String =  {
    val uha : Seq[Char] = input
    uha match {
        case Seq() => "Empty"
        case Seq(first @ _, 'o', 'o')  => "Bar"
        case _ => "Oh" 
    }
}

Calling input on the empty String "" correctly yields "Empty".

However, if I rewrite the first match clause as

case Seq.empty => "Empty"

the matching of "" fails and matches the default clause instead.

Walking through the Scala library source code (which you shouldn't have to do in an ideal world 🙂 ) I believe that both Seq() and Seq.empty will result in RandomAccessSeq.empty. Apparently, this does not concur with the phenomenon described above because only Seq() matches the empty String.

UPDATE: Upon some further experimentation this question can be narrowed down to the following:

val list = List()
   >>> list2: List[Nothing] = List()
val emptySeq = Seq.empty
list == emptySeq
   >>> res1: Boolean = false

This basically means that an empty Seq does not automatically equal Seq.empty .
So when matching against a constant (as opposed to using an extractor as suggested by starblue) this unequality leads to the failing match.
The same is true when interpreting the empty String as a sequence.

Best Answer

This appears to be a bug in the library. Do you want to file the bug or shall I?

scala> Seq.empty  match {case Seq() => "yup"; case _ => "nope"}
res0: java.lang.String = yup

scala> Seq()  match {case Seq.empty => "yup"; case _ => "nope"}
res1: java.lang.String = yup

scala> ("" : Seq[Char]) match {case Seq() => "yup"; case _ => "nope"}    
res2: java.lang.String = yup

scala> ("" : Seq[Char]) match {case Seq.empty => "yup"; case _ => "nope"}
res3: java.lang.String = nope