【问题标题】:Scala: strange behavior in `for` pattern matching for None caseScala:“for”模式匹配无情况下的奇怪行为
【发布时间】:2015-10-23 09:05:41
【问题描述】:

for 循环模式匹配中的奇怪行为:

scala> val a = Seq(Some(1), None)
a: Seq[Option[Int]] = List(Some(1), None)

scala> for (Some(x) <- a) { println(x) }
1

scala> for (None <- a) { println("none") }
none
none

为什么在第二个示例中产生了两个输出'none'?也许这个例子是合成的,不实用,但这种行为是不可预期的。这是错误还是功能?

【问题讨论】:

    标签: scala for-loop pattern-matching


    【解决方案1】:

    你知道吗,这是个bug:

    https://issues.scala-lang.org/browse/SI-9324

    scala> val vs = Seq(Some(1), None)
    vs: Seq[Option[Int]] = List(Some(1), None)
    
    scala> for (n @ None <- vs) println(n)
    None
    

    模糊的规范:

    http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#for-comprehensions-and-for-loops

    比较中游分配,没有出现错误:

    scala> for (v <- vs; None = v) println(v)
    scala.MatchError: Some(1) (of class scala.Some)
      at $anonfun$1.apply(<console>:9)
      at $anonfun$1.apply(<console>:9)
      at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
      at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
      at scala.collection.immutable.List.foreach(List.scala:381)
      at scala.collection.TraversableLike$class.map(TraversableLike.scala:245)
      at scala.collection.immutable.List.map(List.scala:285)
      ... 33 elided
    

    【讨论】:

    • 如果使用此问题的解决方法,它可以工作:scala&gt; for (n @ None &lt;- a) println("none") 产生 none 输出
    • 哈,我也用过n,不过你打字速度更快。
    • 顺便说一句,你可以取消选中绿色,所以人们不认为 Scala 应该是这样工作的。我在这里链接了这个问题,所以 Scala 的人认为人们不会在这些小问题上浪费时间。
    • 顺便说一句,for(Some(x) &lt;- a) 的示例出现在 Odersky 书籍 (SE) 中,但没有None 的示例
    【解决方案2】:

    这是因为None 被解释为变量名:

    scala> for (None <- a) { println(None) } 
    Some(1)
    None
    

    这是没有for的简化示例:

    scala> val None = 5
    None: Int = 5
    
    scala> val Some(a) = Some(5)
    a: Int = 5
    

    【讨论】:

    • for(_ &lt;- a.collect{case None =&gt; ()})
    • for(x &lt;- a if x.isEmpty) {println("none")}
    • 为什么这不是一个错误? case None(因为不可辩驳而被过滤)。
    • val None 不同,因为定义形式与val pattern 形式不同。
    • @som-snytt 我发现specfor (Pattern1) 和val (Pattern2) 之间的唯一区别是_ 接受。但是,您的回答中的示例表明至少违反了规范 Pattern1 =,因为它显示了不同的行为。
    猜你喜欢
    • 1970-01-01
    • 2011-12-26
    • 2019-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-16
    • 2014-09-13
    • 2017-10-28
    相关资源
    最近更新 更多