2
votes

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.

2
Apparently, this will be resolved in Scala 2.8. Looking forward to it. - Johannes Stiehler
Good case, but now expired since the bug is fixed (maybe already years ago). What's the Stackoverflow policy to put these into rest so it wouldn't show up in searches? - akauppi
Could you please somehow mark that this applies to Scala <2.8 only (it's in the comment but we don't start reading there). Meta has an open discussion on what to do with issues s.a. this: meta.stackoverflow.com/questions/252520/… - akauppi

2 Answers

4
votes

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
0
votes

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