views:

342

answers:

2

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.

A: 

In matching the unapply or unapplySeq functions are used, not apply as you seem to believe.

starblue
+2  A: 

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
James Iry
So the bug is really that many subtypes of Seq[A] such as List and RichString are not equal to Seq.empty when they are constructed (with List() resp. ("": Seq[Char])), while others such as RandomAccessSeq are. Could this be intentional for some reason?
Johannes Stiehler