Scala用于理解和部分地图

时间:2010-07-27 14:01:44

标签: scala for-comprehension

Scala语言规范部分 6.19 说:

  

A for comprehension for (p <- e) yield e0被翻译为e.map { case p => e0 }

因此...

scala> val l : List[Either[String, Int]] = List(Left("Bad"), Right(1))
l: List[Either[String,Int]] = List(Left(Bad), Right(1))

scala> for (Left(x) <- l) yield x
res5: List[String] = List(Bad)

到目前为止一切顺利:

scala> l.map { case Left(x) => x }
<console>:13: warning: match is not exhaustive!
missing combination          Right

       l.map { case Left(x) => x }
             ^
scala.MatchError: Right(1)
    at $anonfun$1.apply(<console>:13)
    at ...

为什么第二个版本不起作用?或者更确切地说,为什么第一个版本有效?

3 个答案:

答案 0 :(得分:4)

如果您在for - 理解中使用模式匹配,编译器实际上会在filter之前插入对instanceOf的调用 - 在应用map之前进行检查。

编辑:

同样在6.19节中,它说:

  

如果g被转换为单个生成器,则生成器p&lt; -e后跟保护器p&lt; -e.withFilter((x1,...,xn)=&gt; g)其中x1,... ,xn是p。

的自由变量

生成器先前定义为:

  

Generator :: = Pattern1'&lt; - 'Expr [Guard]

检查字节码时,您会在调用filter之前看到map的来电。

答案 1 :(得分:2)

作为Eastsun评论的补充:Scala 2.8有一个方法收集,可以在你的例子中使用:

l.collect { case Left(x) => x }
//--> List[String] = List(Bad)

答案 2 :(得分:1)

Scala 2.7语言规范,第83页,从底部开始的第二段(这里没有2.8规范)。插入用于生成器模式匹配的过滤器是for-comprehension翻译过程的第一步。

有一点需要注意,我最后一次检查时,这对于打字模式不起作用,这可能会令人惊讶。所以在你的例子中

for(x:Left <- l) yield x  

无效,抛出类型错误