scala – 匹配可能不是详尽的警告是不正确的
所以
scala编译器抱怨模式匹配可能不是foo方法的穷举,我想知道为什么.这是代码:
abstract class Foo { def foo(that: Foo): Unit = (this,that) match { case (Foo_1(),Foo_1()) => //case 1 case (Foo_1(),Foo_2()) => //case 2 case (Foo_2(),Foo_1()) => //case 3 case (Foo_2(),Foo_2()) => //case 4 // Compiler warning } def fooThis(): Unit = this match { case Foo_1() => //do something case Foo_2() => //do something // Works fine } def fooThat(that: Foo): Unit = that match { case Foo_1() => //do something case Foo_2() => //do something // Works fine } } case class Foo_1() extends Foo case class Foo_2() extends Foo 这是错误: Warning:(5,32) match may not be exhaustive. It would fail on the following inputs: (Foo(),_),(Foo_1(),(Foo_2(),(_,Foo()),Foo_1()),Foo_2()),_) def foo(that: Foo): Unit = (this,that) match { 由于这个和Foo类型,并且Foo只能是Foo_1或Foo_2类型,因此foo中的情况都是可能的组合. 为了完整起见,我添加了fooThis和fooThat,并表明匹配Foo_1和Foo_2就足够了.编译器消息表明还有其他类型可以匹配(即Foo和_). 那么为什么会出现这个警告呢? 有关: > Scala bug: fixed in 2.12.0-M4.我的scala欢迎辞:
> Scala bug: false match not exhaustive warning on (unsealed,sealed) tuple 编辑 一旦你使用元组,编译器似乎就会抱怨.如果我们将一个虚拟变量添加到fooThis,如下所示 def fooThis(): Unit = (this,Foo_1()) match { case (Foo_1(),_) => //do something case (Foo_2(),_) => //do something } 我们得到以下编译器警告 Warning:(13,27) match may not be exhaustive. It would fail on the following input: (_,_) def fooThis(): Unit = (this,Foo_1()) match { 解决方法
Scala编译器不会为非密封特征(如您的Foo)提供详尽的匹配警告.这解释了为什么fooThis和fooThat编译没有警告.
如果你想在这里发出警告(你应该,因为它们在运行时比MatchError异常更好),你有几个选择: >让Foo密封.这会创建一个ADT,这样可以安全地进行模式匹配,因为当您忘记案例时,您将获得详尽的警告.选项是您可能从标准库中熟悉的ADT.在这里,你已经有了Foo_1和Foo_2的案例,所以你不会得到一个详尽的警告.但如果你忘了这两种情况,你会的.你可能想让Foo_1和Foo_2成为最终决赛. 另一方面,Scala编译器将为最终案例类(如Tuple2)提供详尽的匹配警告,这是您在foo方法中匹配的内容. 要回答“为什么会显示警告?”,请考虑如果我们这样做会发生什么: case class Foo3() extends Foo val foo3 = Foo3() foo3.foo(foo3) (答案:它在运行时抛出MatchError.) 警告是Scala编译器帮助您在运行时避免异常的方法.如果你想让警告消失,你可以: >让Foo密封(再次创建一个ADT),防止Foo3潜入其他地方. 不要做3号,因为当有人介绍Foo3时,它会让你在运行时容易受到MatchErrors的攻击. 所以,也许问题不是“为什么foo中的匹配会产生警告”,而是“为什么fooThis和foo中的匹配不会产生警告”. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |