gpt4 book ai didi

scala - 匹配可能不是详尽的警告是不正确的

转载 作者:行者123 更新时间:2023-12-05 00:51:18 24 4
gpt4 key购买 nike

因此,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 {

thisthat属于 Foo 类型, 和 Foo只能是 Foo_1 类型或 Foo_2 , foo中的案例都是可能的组合。

我加了 fooThisfooThat为了完整起见并显示匹配 Foo_1Foo_2就足够了。编译器消息表明还有其他类型可以匹配(即 Foo_ )。

那么为什么会显示此警告?

有关的:
  • Scala bug: fixed in 2.12.0-M4 .我的 Scala 欢迎信息:

    Welcome to Scala 2.12.1 (Java HotSpot(TM) Client VM, Java 1.8.0_131).

  • 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)给出详尽的匹配警告。这解释了为什么fooThisfooThat编译没有警告。

    如果你想在这里发出警告(你应该这样做,因为它们在运行时比 MatchError 异常要好)你有几个选择:

  • 制作 Foo密封。这将创建一个 ADT ,这对于模式匹配来说是安全的,因为当你忘记一个案例时你会得到详尽的警告。 Option是您可能熟悉的标准库中的 ADT。在这里,您已经获得了 Foo_1 的案例和 Foo_2 ,因此您不会收到详尽警告。但是,如果您忘记任何一种情况,您就会忘记。您可能想要制作 Foo_1Foo_2最后,当你在它的时候。
  • 离开 Foo未密封,使用 Typelevel Scala并启用其 -Xlint:strict-unsealed-patmat警告。

  • 另一方面,Scala 编译器将为最终的案例类(如 Tuple2)给出详尽的匹配警告。 ,这就是您在 foo 中匹配的内容方法。

    要回答“为什么显示警告?”,请考虑如果我们这样做会发生什么:
    case class Foo3() extends Foo
    val foo3 = Foo3()
    foo3.foo(foo3)

    (答案:它在运行时抛出 MatchError。)

    警告是 Scala 编译器帮助您在运行时避免异常的方式。如果您想让警告消失,您可以:
  • 制作 Foo密封(再次创建 ADT),防止 Foo3从潜入别处。
  • 添加通配符 case _ => ... .
  • 取消选中匹配:((this, that): @unchecked) match { ... .

  • 不要做第 3 条,因为它会让你容易受到 MatchError 的影响。 s 在运行时有人介绍 Foo3 .

    所以,也许问题不是真正的“为什么 foo 中的匹配会产生警告”,而是“为什么 不会 fooThisfooThat 中的匹配产生警告”。

    关于scala - 匹配可能不是详尽的警告是不正确的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44578016/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com