When you pattern match again Lists, you can use Nil to check for empty list. However, if the underlying type is an Iterable, you can still check for Nil, and it will break for empty Sets, etc... See following REPL session:
scala> val l: Iterable[Int] = List()
l: Iterable[Int] = List()
scala> l match {
| case Nil => 1
| case _ => 2
| }
res0: Int = 1
scala> val l: Iterable[Int] = Set()
l: Iterable[Int] = Set()
scala> l match {
| case Nil => 1
| case _ => 2
| }
res2: Int = 2
Question is - how can I prevent this kind of issue? Obviously, if l is a type List, it's no bug. And if l is of type Set, it won't compile. But what if we have a class that has a list, define a function that pattern matches in this way, and then someone changes the class to take a generic iterable instead? Is this Nil vs. _ pattern match a bad idea in general?
One possibility is to use a guard:
scala> val xs: Iterable[Int] = Set()
xs: Iterable[Int] = Set()
scala> xs match { case xs if xs.isEmpty => 1 case _ => 2 }
res0: Int = 1
Another way to do this is to use an if-else-expression (works best if you only have one or two conditions to check):
scala> if (xs.isEmpty) 1 else 2
res1: Int = 1
Convert the scrutinee to a list to eliminate doubt.
l.toList match {
case Nil => 1
case xs => 2
}
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