gpt4 book ai didi

在元组中返回 null 时,Scala 模式匹配会引发匹配错误

转载 作者:行者123 更新时间:2023-12-05 00:56:55 25 4
gpt4 key购买 nike

下面是两个片段,我无法理解为什么一个成功执行而另一个抛出运行时异常。

片段1:

val str = "HELP"

val perfectTuple: (String, String) = str match {
case "NO-HELP" => ("First Help", "Second Help")
case "OTHER-HELP" => ("I won't Help!", "Even,I won't Help!")
case "HELP" => (null,"Single Help")
case _ => throw new NoSuchMethodException

}

片段2:
val str = "HELP"

val (firstPart:String, secondPart:String) = str match {
case "NO-HELP" => ("First Help", "Second Help")
case "OTHER-HELP" => ("I won't Help!", "Even,I won't Help!")
case "HELP" => (null,"Single Help")
case _ => throw new NoSuchMethodException
}

===========================

两个片段之间几乎没有区别。一个将返回的元组存储到一个类型为 tuple2 的值“perfectTuple”中,这个元组被成功执行。

另一个从元组 2 中提取值并将它们存储到字符串值中并引发运行时“scala.matchError”。

这是scala中的错误吗?

我在 scala 2.10.5 和 2.11.7 上试过这个

提前致谢。

==============

还有一种情况,在这种情况下,我可以将 null 从模式匹配中分配给一个字符串,而这个工作绝对完美:
片段3:
val str = "HELP"

val assignNullToString: String = str match {

case "NO-HELP" => "ONE"
case "OTHER-HELP" => "TWO"
case "HELP" => null
case _ => throw new NoSuchMethodException
}

所以我假设,不是我将 null 分配给 String 导致了问题,它与 Tuple 有关吗? Snippet 2 有什么问题,而 Snippet 1 运行得非常好。

最佳答案

那么第二个例子使用 unapplycase class Tuple2 .

现在,我还没有看Tuple2.unapply的优化代码但我猜想在某些时候它会对元组的值进行类型匹配。

而且一个人根本无法在 null 上键入匹配项.

val str: Any = null

str match {
case _: String => "yay"
case other => "damn"
}
|-> res1: String = damn

更新

让我们稍微剖析一下您的第二个示例:
val str = "HELP"

val (firstPart:String, secondPart:String) = str match {
case "NO-HELP" => ("First Help", "Second Help")
case "OTHER-HELP" => ("I won't Help!", "Even,I won't Help!")
case "HELP" => (null,"Single Help")
case _ => throw new NoSuchMethodException
}

当我们提取匹配时,我们得到:
val tuple: (String, String) = str match {
case "NO-HELP" => ("First Help", "Second Help")
case "OTHER-HELP" => ("I won't Help!", "Even,I won't Help!")
case "HELP" => (null,"Single Help")
case _ => throw new NoSuchMethodException
}

现在,您将其放入 unapply Tuple2的功能.看看签名:
def unapply[A, B](tuple: Tuple2[_, _]): Option[(A, B)]

所以传入元组的值的类型被删除了!
然而,当你说
val (first: String, second: String) = tuple

您调用 Tuple2.unapply带类型参数 [String, String] ,明确要求结果为 (String, String) .

为了能够返回 Option[(String, String)] , unapply 函数必须键入匹配两个值。

可以想象 Tuple2伴侣对象看起来像,但实际上更有效和更复杂:
object Tuple2 {
def apply[A, B](_1: A, _2: B): Tuple2[A, B] = new Tuple2(_1, _2)

def unapply[A, B](tuple: Tuple2[_, _]): Option[(A, B)] = {
val a: Option[A] = tuple._1 match { case a: A => Some(a) }
val b: Option[B] = tuple._2 match { case b: B => Some(b) }

a.zip(b).headOption
}

现在这是会引发 MatchError 的行:
  val a: Option[A] = tuple._1 match { case a: A => Some(a) }

前面说了, Tuple2的优化代码我没看,但我有理由相信这与实际发生的情况非常接近。

您当然可以随时放宽您的要求:
val str = "HELP"

val (firstPart, secondPart) = str match {
case "NO-HELP" => ("First Help", "Second Help")
case "OTHER-HELP" => ("I won't Help!", "Even,I won't Help!")
case "HELP" => (null,"Single Help")
case _ => throw new NoSuchMethodException
}

在大多数情况下应该工作得很好,但可能只会推迟痛苦。

编辑 2

我建议始终注意这样一个事实,即在使用提取器绑定(bind) val 时,使用语法糖进行模式匹配,因为模式匹配可能总是因匹配错误而失败。

这里有一些明显的例子,我见过几次以不太明显的方式发生。
val foo = ("lorem", 2)
val (lorem: String, bad: String) = foo // fail

case class Bar(name: String, age: Option[Int])
val bar = Bar("Sam", None)
val Bar(name, Some(age)) = bar // fail

关于在元组中返回 null 时,Scala 模式匹配会引发匹配错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35559268/

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