Scala 用于理解和部分映射

发布于 2024-09-11 18:45:24 字数 773 浏览 7 评论 0原文

Scala 语言规范部分 6.19 说:

A 的理解 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 ...

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

The Scala language specification section 6.19 says:

A for comprehension for (p <- e) yield e0 is translated to e.map { case p => e0 }

So...

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)

So far so good:

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 ...

Why does the second version not work? Or rather, why does the first version work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

肥爪爪 2024-09-18 18:45:24

如果您在 for 理解中使用模式匹配,编译器实际上会在应用 之前插入对 filter 的调用,并使用 instanceOf 检查>地图

编辑:

第 6.19 节中还提到:

如果 g 被转换为单个生成器 p <- e.withFilter((x1, ..., xn) => g ),则生成器 p <- e 后跟一个防护,其中 x1, ... , xn 是 p 的自由变量。

生成器之前定义为:

生成器 ::= Pattern1 '<-' Expr [Guard]

检查字节码时,您将看到对 filter 的调用位于对 map 的调用之前。

If you use pattern matching in your for-comprehension the compiler will actually insert a call to filter with an instanceOf-check before applying the map.

EDIT:

Also in section 6.19 it says:

A generator p <- e followed by a guard if g is translated to a single generator p <- e.withFilter((x1, ..., xn) => g ) where x1, ..., xn are the free variables of p.

A generator is defined earlier on as:

Generator ::= Pattern1 ‘<-’ Expr [Guard]

When inspecting the bytecode you will see the call to filter preceding the call to map.

脱离于你 2024-09-18 18:45:24

作为Eastsun评论的补充:Scala 2.8有一个方法collect,它可以在你的示例中工作:

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

As an addition to Eastsun's remarks: Scala 2.8 has a method collect, which would work in your example:

l.collect { case Left(x) => x }
//--> List[String] = List(Bad)
完美的未来在梦里 2024-09-18 18:45:24

Scala 2.7 语言规范,第 83 页,倒数第二段(此处没有 2.8 规范)。插入用于生成器模式匹配的过滤器是理解翻译过程的第一步。

需要注意的是,我上次检查时,这不适用于键入的模式,这可能会令人惊讶。所以在你的例子中

for(x:Left <- l) yield x  

是行不通的,会抛出类型错误

Scala 2.7 language specification, page 83, second paragraph from the bottom (don't have the 2.8 spec here). Inserting filters for generator pattern-matching is the first step in the for-comprehension translation process.

One caveat, the last time I checked, this doesn't work for typed patterns, which can be surprising. So in your example

for(x:Left <- l) yield x  

wouldn't work, throwing a type error

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文