【问题标题】:Strange pattern matching behaviour with AnyRefAnyRef 的奇怪模式匹配行为
【发布时间】:2011-12-26 11:42:09
【问题描述】:
def test1(a: Any) = a match {
  case x: AnyRef => "AnyRef"
  case _ => "None of the above"
}

def test2(a: Any) = a match {
  case x: Double if x > 2 => "Double > 2"
  case x: AnyRef => "AnyRef"
  case _ => "None of the above"
}

请有人能解释一下为什么在下面的第一种情况下1.0 匹配AnyRef,但在第二种情况下却不匹配。 (Scala 2.9.0-1)

scala> test1(1.0)
res28: java.lang.String = AnyRef

scala> test2(1.0)
res29: java.lang.String = None of the above

编辑 - Scala 2.10 2013 年 1 月更新:新的模式匹配器修复了此行为(或至少使其保持一致)并且方法 test2 现在返回与 test1 一样的“AnyRef” .

【问题讨论】:

  • 编译时生成的是 if(a instanceof Double) { if(a > 2) { return "Double > 2"} else { return "None of the Above" } } else { if( a instanceof Object) { return "AnyRef"} else {return "None of the Above"}} 。因此,除非有人在 scala 规范中找到某些东西,否则我认为这是 scala 编译器错误
  • 1.0Double 的子类型,它是 Any 但不是 AnyRef 的子类型,与 java.lang.Double 不同。所以我什至想知道为什么1.0test1 中的AnyRef 匹配。
  • 我删除了我的答案。这不是一个错误——我没有注意到你正在匹配AnyRef。雷克斯科尔是正确的。
  • @PeterSchmitz:根据规范,你是对的。

标签: scala pattern-matching


【解决方案1】:

这是因为Any 实际上只是一个Object。拥有Double 有一个方便的虚构——它实际上是java.lang.Double,它在匹配语句中为您自动拆箱。不幸的是,Scala 无法判断它是否找到java.lang.Double,如果它应该被解释为Doublejava.lang.Double——在后一种情况下,AnyRef 应该抓住它。确实如此。但是,如果您专门询问 Double,它知道它应该取消装箱,然后无需检查AnyRef 案例。 (事实上​​,如果您打算将其设为 java.lang.Double,它也会将其拆箱——它无法区分。)

这是否是理想行为值得商榷,但合乎逻辑。

【讨论】:

  • 谢谢,现在我明白为什么1.0test1 匹配了。
  • @RexKerr 我不确定我是否还买它。 “在后一种情况下, AnyRef 应该抓住它。”除了它没有因为“以上都没有”被打印出来。我还假设匹配案例的结果应该等于它组成部分函数...val x:PartialFunction[Any, String] = {case x:Double if x > 2 => "Double > 2"} val y:PartialFunction[Any, String] = {case x:AnyRef => "AnyRef"} val z:PartialFunction[Any, String] = {case _ => "None of the Above"} println(test2(1.0)) // => None of the Above val chain = x orElse y orElse z println(chain(1.0)) // => AnyRef
  • @DanielHinojosa - 正如我所说,我不确定这是否理想:AnyRef 应该抓住它除非你指定你想要Double。有人可能会争辩说,Double 上的守卫应该表明你只希望 那些 Doubles 被认为不是-AnyRef,其余的应该被AnyRef 正常捕获.
  • Scala 规范中是否描述了这种行为?我真的很想知道如何将目前的行为形式化。
  • @RexKerr:嗯,它不会泛化到AnyVal children 之外,也不会超出不同情况的排列。无论如何,我确实在规范中查找过,但也没有。 12.2,也不是秒。 8.1-8.2 提示了任何此类问题,因此第一个代码片段与规范不符。但考虑到性能成本,我担心与AnyRef 匹配的那一天会起作用并过滤掉与AnyVal 的匹配。我认为匹配AnyRef 应该触发警告或错误,建议匹配Any,尤其是因为AnyVal 已经被禁止。
猜你喜欢
  • 1970-01-01
  • 2013-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-03
  • 2019-12-30
  • 1970-01-01
相关资源
最近更新 更多