考虑以下损坏的函数:
def sum (list : Seq[Int]) : Int = list match {
case Nil => 0
case head :: tail => head + sum(tail)
}
在这里,该函数本应使用List[Int]
,但被重构为接受Seq[Int]
,因此在编译器没有注意到的情况下被破坏。
Scala的不完全模式匹配检测中的这个巨大漏洞使它几乎毫无用处。
我想有一种系统地发现这些问题的方法。具体来说,我希望编译器在每个instanceof
引导的模式匹配上都发出错误/警告,即我只希望允许在密封层次结构和自定义匹配器上进行模式匹配。
是否存在用于对模式匹配安全性进行保守(而不是任意)检查的现有编译器选项/插件?
看看M.Odersky的这个答案。
摘要
对非密封层次结构的匹配进行检查是可行的,并非微不足道,而且尚未实现。
Nil
和::
显然是构造List
的方法,但并非所有Seq
的影响都恰好是Lists
,因此可以预期Scala类型检查器会以类型错误为由拒绝此程序。正确的
错了。试试这个,你就会明白我的意思:
def sum (list : Seq[Int]) : Int = list match {
case Nil => 0
case head :: tail => head + sum(tail)
case _ => -1
}
> sum(Array(1,2,3).toSeq)
res1: Int = -1
> sum(List(1,2,3))
res2: Int = 6
所以你看,一些Seq
影响可能能够用Nil
和::
解构,所以那些可以的,会的。那些做不到的人将在模式匹配中失败,然后继续前进,尝试下一场比赛。Nil
和::
足以覆盖List
的所有可能性,但不能覆盖Seq
的所有可能性。在子类型、便利性和类型安全性之间有一个折衷。目前的解决方案是:重构时要更加小心。