Scala - 匹配选项元组



我有:

val foo = Some(List(1, 2, 3)) -> Some("y")

我想投匹配它:

foo match {
    case (Some(x), Some(y)) => println(x + " " + y)
    case _ => println("error")

这适用于Some(List(1, 2, 3) -> Some("score"))但不适用于Some(List(1, 2, 3) -> NoneNone -> Some("y")None -> None

error: constructor cannot be instantiated to expected type;
     found   : Some[A]
     required: None.type
error: not found: value ...

为什么?

当然,我可以使用getOrElse()但这看起来并不那么优雅。

非常感谢,卡斯滕

更新:

foo match {
 case (x: Some[List[Int]], y: Some[Int]) => println(x.get)
 case _ => println("error")
}

也失败了:

error: pattern type is incompatible with expected type;
 found   : Some[Int]
 required: None.type

我认为case _会照顾到这一点。

它是编译器告诉你一些事情。如果你有一个表达式,比如

val foo = Some(List(1, 2, 3)) -> None

它将具有类型(Some[List[Int]],None.type),您可以通过在scala控制台中的表达式中键入轻松看到

scala> val foo = Some(List(1, 2, 3)) -> None
foo: (Some[List[Int]], None.type) = (Some(List(1, 2, 3)),None)

所以你在编译时知道元组的第二个元素只能是 None,与 Some 的匹配永远不会成功。因此出现错误消息。

如果你给foo一个限制较少的类型,它将起作用。

val foo : (Option[List[Int]], Option[String]) = Some(List(1, 2, 3) -> None

请注意,这完全是应该的。匹配永远不会发生的事情几乎肯定是一个错误。您必须向上转换为 any 以避免编译时错误(但随后您将获得运行时错误。

在下面的代码中,Scala 会在foo match上收到编译错误,但使用 foo2/foo3 正确编译和运行:

val foo = None -> None
val foo2: (Option[Any], Option[Any]) = None -> None
val foo3: (Option[Any], Option[Any]) = foo
foo match {
  case (Some(x), Some(y)) => println(x + " " + y)
  case _ => println("error")
}

最新更新