如何让Scala编译器识别Vector的穷举匹配?
Scala Vector 穷举匹配的编译器警告解决方法
你这段代码逻辑上已经覆盖了Vector[Int]的空和非空两种情况,但Scala编译器的模式匹配穷举检查没有识别出ns :+ n能覆盖所有非空向量,因此抛出了非穷举警告。以下是几种无需抑制警告、能让编译器认可的正确解构方式:
原代码与警告
def testExhaustiveness(v: Vector[Int]) = { v match { case Vector() => println("v is empty") case ns :+ n => println("v has at least one element") } } @main def main = { testExhaustiveness(Vector()) // v is empty testExhaustiveness(Vector(1)) // v has at least one element testExhaustiveness(Vector(1, 2)) // v has at least one element }
编译器警告:
18 | v match { | ^ |match may not be exhaustive. | |It would fail on pattern case: Vector(_, _*), Vector(_, _*), Vector(_, _*), Vector(_, _*), Vector(_, _*), Vector(_, _*) | | longer explanation available when compiling with `-explain`
方法1:显式区分空/非空后匹配
先通过isEmpty判断向量状态,再对非空向量做模式匹配,这种方式能让编译器明确识别穷举覆盖:
def testExhaustiveness(v: Vector[Int]) = { if (v.isEmpty) println("v is empty") else v match { case ns :+ n => println(s"v has at least one element, last is $n") } }
方法2:使用序列模式覆盖非空情况
利用Vector的unapplySeq支持的Vector(_, _*)模式,这种写法能被编译器正确识别为覆盖所有非空向量的情况:
def testExhaustiveness(v: Vector[Int]) = { v match { case Vector() => println("v is empty") case Vector(_, _*) => println("v has at least one element") } }
如果需要获取最后一个元素,可以结合last方法:
def testExhaustiveness(v: Vector[Int]) = { v match { case Vector() => println("v is empty") case nonEmptyVec if nonEmptyVec.nonEmpty => val n = nonEmptyVec.last println(s"v has at least one element, last is $n") } }
方法3:通配符兜底(不推荐)
虽然逻辑冗余,但直接添加通配符case可以消除警告,适合临时快速解决:
def testExhaustiveness(v: Vector[Int]) = { v match { case Vector() => println("v is empty") case ns :+ n => println("v has at least one element") case _ => println("v has at least one element") } }
警告原因
Scala编译器对:+这类后缀模式的穷举性分析存在局限,无法自动推断出ns :+ n能覆盖所有非空Vector场景。而显式的序列模式或前置空/非空判断,能让编译器正确识别匹配的穷举性。
内容的提问来源于stack exchange,提问作者doliphin
相关产品推荐
相关产品推荐

