Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I match on a Seq.empty?

Tags:

scala

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

like image 755
cool breeze Avatar asked Jan 04 '17 22:01

cool breeze


2 Answers

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.

like image 66
jwvh Avatar answered Nov 11 '22 17:11

jwvh


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.

like image 25
evan.oman Avatar answered Nov 11 '22 17:11

evan.oman