Freewind
Freewind

Reputation: 198188

Why scala compiler sometimes give warning on "pattern matching", sometimes not?

Define a list first:

val list = List(1,2,3)

Scala compiler gives warning (even if it can match):

list match {
  case head :: tail => println(s"h:${head} ~ t: ${tail}")
}

Scala compiler won't give warning (even if it can't match):

list match {
  case List(a,b) => println("!!!")
}

I can't understand the second one

Upvotes: 2

Views: 71

Answers (1)

wingedsubmariner
wingedsubmariner

Reputation: 13667

The "match may not be exhaustive" warning is only given when pattern matching on a type that is a sealed class and you have cases for only a subset of the subclasses or objects. List is a sealed class with a subclass :: and a subobject Nil, something like:

sealed abstract class List[+T]
class ::[+T] extends List[+T]
object Nil extends List[Nothing]

If you have a match and don't have a case for :: and one for Nil, and also don't have a case that might match any List, Scala knows the match isn't exhaustive and will report it. A case _ would match anything and will prevent the warning. But List(a, b) also prevents the warning, because Scala doesn't know if it only matches some of the subclasses.

When you use List as an extractor, as in List(a, b), you are using the extractor List.unapplySeq to take apart the matched value. Scala doesn't try to make assumptions about how the extractor behaves, and therefore doesn't know that the match isn't exhaustive. Without knowing the implementation details of List.unapplySeq, there is no way to know it won't happily match everything and return the required two values.

Upvotes: 11

Related Questions