Pedro Gordo
Pedro Gordo

Reputation: 1865

Selector of pattern match being exhaustive

Looking at the Scala doc for sealed classes, it says:

If the selector of a pattern match is an instance of a sealed class, the compilation of pattern matching can emit warnings which diagnose that a given set of patterns is not exhaustive, i.e. that there is a possibility of a MatchError being raised at run-time.

I don't quite understand what they meant in this paragraph. My understanding is that if a switch case, doesn't cover all the possibilities, then we'll get a warning at compile time, saying we might get an error at run time. Is this correct?

I find it strange, because how can we cover ALL the scenarios in a switch case? We would have to match all possible strings, which is just silly, so I take it my understanding is incorrect. Someone care to elucidate, please?

Upvotes: 2

Views: 963

Answers (3)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149538

What the paragraph is saying is that in-case you have a fixed hierarchy structure like this:

sealed trait Foo
class Bar extends Foo
class Baz extends Foo
class Zab extends Foo 

Then when you pattern match on it, the compiler can infer if you've attempted to match on all possible types extending the sealed trait, in this example:

def f(foo: Foo) = foo match {
     | case _: Bar => println("bar")
     | case _: Baz => println("baz")
     | }

<console>:13: warning: match may not be exhaustive.
It would fail on the following input: Zab()
       def f(foo: Foo) = foo match {
                         ^
f: (foo: Foo)Unit

Note the beginning of the document says:

A sealed class may not be directly inherited, except if the inheriting template is defined in the same source file as the inherited class.

This is unique to Scala, and can't be done in Java. A final class in Java cannot be inherited even if declared inside the same file. This is why this logic won't work for String in Scala, which is an alias for java.lang.String. The compiler warning may only be emitted for Scala types that match the above criteria.

Upvotes: 4

Filippo Costa
Filippo Costa

Reputation: 498

The wildcard character allows us to cover all the scenarios.

something match {
  case one => ...
  case two => ...
  case _ => ...
}

It is selected whenever all other cases don't match; that is, it is the default case. Further information here.

Upvotes: 0

Alexey Romanov
Alexey Romanov

Reputation: 170735

I find it strange, because how can we cover ALL the scenarios in a switch case? We would have to match all possible strings

Yes, if the selector has type String (except it isn't a sealed class, because that's a Scala concept and String is a Java class).

which is just silly

No. For strings, you just need a catch-all case, e.g.

val x: String = ...
x match {
  case "a" => ...
  case "b" => ...
  case _ => ...
}

is an exhaustive match: whatever x is, it matches one of the cases. More usefully, you can have:

val x: Option[A] = ...
x match {
  case Some(y) => ...
  case None => ...
}

and the compiler will be aware the match is exhaustive even without a catch-all case.

Upvotes: 3

Related Questions