【问题标题】:Scala Pattern Matching Compiler WarningScala 模式匹配编译器警告
【发布时间】:2012-07-07 16:52:12
【问题描述】:

我在我的代码中造成了一个更难找到我想要的错误,以及我希望将来避免的错误。我希望 Scala 编译器会警告我我的错误(除非我遗漏了什么)。

我已将其简化为小事:

Vector.maybeGetVector match {
  case v:Vector => true
  case _ => false
}

case class Vector(x:Int, y:Int)

object Vector {
  def maybeGetVector : Option[Vector] = Some(new Vector(1,2))
}

我使用wildcard 而不是None 的唯一原因是我只想匹配返回的Option 的子类型。

我期待一个编译器警告,因为很容易推断第一个 case 语句包含无法访问的代码。 Option[Vector] 不能是 Vector 的子类型。

奇怪的是,如果我添加以下 case 语句:

 case i:Int => false

它会引发错误并告诉我Option[Vector] 是必需的。

在命名约定之外,有没有办法以这种方式防止程序员错误。唯一能与Option 匹配的是Some/None/null。我觉得我遗漏了一些明显的东西。

【问题讨论】:

  • 我认为这值得开一张增强票。 Scala 2.10 有一个全新的模式匹配代码。旧的不仅没有捕捉到这一点,而且漏洞百出,很难理解和修复,更不用说改进了。

标签: scala


【解决方案1】:

如果您使用 final 修饰符定义 Vector 类,您将收到预期的“模式类型与预期类型不兼容”错误。

对我来说,Scala 认为您的 Option[Vector] 可能以某种方式是 Vector 子类型的一个实例。 (这对我来说似乎是不可能的,但我认为这是起作用的原因。)使 Vector 最终排除了这种看似遥远的可能性。

所以,如果第一个 case 语句应该是不可访问的,那不是因为,正如你所说,Vector 不能是 Option[Vector] 的子类型;而是因为 Option[Vector] 不能是 Vector 子类型的实例。也许这就是你的意思:)

【讨论】:

  • 是的,你在最后一点上是对的,必须阅读大约 5 次才能弄明白 :)
  • 添加 final 给出了所需的错误。有点奇怪,Option 是一个密封的抽象类,它不像是一个可混合的特征(Vector 的子类型可以混合等)。
猜你喜欢
  • 2014-04-13
  • 2016-05-17
  • 1970-01-01
  • 1970-01-01
  • 2014-04-12
  • 1970-01-01
  • 1970-01-01
  • 2018-07-10
  • 2014-06-10
相关资源
最近更新 更多