Pattern match not-exhaustive, no warning


#1

I have defined a local function as follows:

    def loop(a: List[Int], i: Int, candidate: Option[(Int, Int, Int)]): Option[Int] = {
      println(s"a=$a  i=$i  candidate=$candidate")
      (a, candidate) match {
        case (Nil, Some((_, _, candidateIndex))) => Some(candidateIndex)
        // no candidate available
        case (ah :: at, None) => loop(at, i + 1, Some((ah, 1, i)))
        // next item equal to current candidate
        case (ah :: at, Some((c, cc, ci))) if ah == c => loop(at, i + 1, Some((c, cc + 1, ci)))
        // next item different from candidate,  no alternate available
        case (ah :: at, Some((c, 1, _)))   if ah != c => loop(at, i + 1, None)
        // next item different from candidate, alternate available
        case (ah :: at, Some((c, cc, ci))) if ah != c => loop(at, i + 1, Some((c, cc - 1, ci)))
      }

At runtime I get an error, because the local function, loop, is called with (Nil,4,None),
and there is no case for (Nil,None). However, I don’t see any warning about this when I compile.
It is obvious how to fix the problem when the runtime error occurs, but it would be great if
I could avoid this problem in the future.

Can someone suggest what I should be doing that I’m missing?


#2

There are issues here and here with discussion.

I haven’t assimilated all the wisdom, but I assume the advice would be to move your guards to the right of the arrow. Which is too bad, because then you have to use parens. In your case, more parens.


#3

Indeed moving the guards to the right would be bad because it would change the logical semantics of the pattern matching . I’d have two patterns the same, thus one unreachable. :frowning: