I got an interesting compiler warning on the code below.
418[info] Compiling 10 Scala sources to /builds/jnewton/earthmap/globe/target/scala-2.13/test-classes ...
419[warn] /builds/jnewton/earthmap/globe/src/test/scala/enhancements/EnhancementTest4.scala:93:7: match may not be exhaustive.
420[warn] It would fail on the following input: List(_)
421[warn] sorted match {
422[warn] ^
423[warn] one warning found
Here is the offending code. It looks to me like there is a case for List(_). Does this warning make sense? Maybe there’s something obvious that I don’t see?
@tailrec
def check(sorted:List[City]):Unit = {
sorted match {
case List() => ()
case List(_) => ()
case c1::c2::cs if c1.loc.lat == c2.loc.lat =>
assert(c1.loc.lon <= c2.loc.lon, s"cities $c1 and $c2 not sorted west to east")
check(c1::cs)
case c1::c2::cs =>
assert(c1.loc.lat >= c2.loc.lat, s"cities $c1 and $c2 not sorted north to south")
check(c2::cs)
}
}
I can think of many ways to fix the code to avoid the warning. But I’m just surprised that the warning is emitted in the first place.
I remember some discussion about this, I think from dwijnand somewhere on Github, that this is hard to get right.
Of course, you could restructure your code:
def check(sorted:List[City]):Unit = {
sorted match {
case c1::c2::cs if c1.loc.lat == c2.loc.lat =>
assert(c1.loc.lon <= c2.loc.lon, s"cities $c1 and $c2 not sorted west to east")
check(c1::cs)
case c1::c2::cs =>
assert(c1.loc.lat >= c2.loc.lat, s"cities $c1 and $c2 not sorted north to south")
check(c2::cs)
case _ =>
}
}
Oh, and maybe a non-recursive solution might be more readable:
sorted.sliding(2).foreach {
case (c1, c2) => ...
}