I tried matching a seq like this:
val users: Seq[User] = ....
users match {
case Seq.empty => ....
case ..
}
I got an error saying:
stable identifier required, but scala.this.Predef.Set.empty found.
Can someone explain why I can't do this? i.e. the theory behind it
Both Seq.apply
and Seq.empty
are implemented in GenericCompanion, which has no unapply
method, so you'd think that pattern matching wouldn't be possible, but you're still able to pattern match on Seq()
because Seq.unapplySeq()
, implemented in SeqFactory, makes that available.
From the unapplySeq()
docs:
This method is called in a pattern match { case Seq(...) => }.
more background
Collections make pattern matching possible via the unapplySeq()
method, which gets called when the compiler sees something like case List() => ...
.
It's interesting that List(42)
is the same thing as List.apply(42)
but not so in pattern matching:
lst match {
case List(8) => ... // OK
case List.apply(8) => ... // won't compile
}
The same principle applies to Seq()
and Seq.empty
.
Match on Seq()
or Nil
instead:
scala> Seq.empty
res0: Seq[Nothing] = List()
scala> val a = Seq(1,2,3)
a: Seq[Int] = List(1, 2, 3)
scala> val b = Seq()
b: Seq[Nothing] = List()
scala> a match {case Seq() => "empty"
| case _ => "other"
| }
res1: String = other
scala> b match {case Seq() => "empty"
| case _ => "other"
| }
res2: String = empty
See @jwvh's answer for technical reasons why.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With