【问题标题】:How to yield multiple values?如何产生多个值?
【发布时间】:2018-10-19 15:10:42
【问题描述】:

我有这样的理解:

val ao = Option(1)
val bo = Option(2)
val (x,y) = for (a <- ao; b <- bo) yield (a+b, b+a*2)

但是这不起作用。对于理解返回 Option[(Int,Int)] 但不能分配给单个 x 和 y。

如果我这样做:

val Some((x,y)) = for ...

yield None 时会导致异常。

如何实现这个目标?我希望 x 和 y 为 Option[Int]。我希望在不使用 x._1x.getOrElsematch 之类的情况下找到一个优雅的解决方案

【问题讨论】:

  • unzip 返回Iterable 列表,这很可悲……嗯。
  • 以下是否有帮助:val (x, y) = (Option(1), Option(2)) match { case (Some(a), Some(b)) =&gt; (Some(a+b), Some(b+a*2)); case _ =&gt; (None, None) } 其中xyOptions

标签: scala pattern-matching option


【解决方案1】:

应该unzip,但不幸的是,unzip 返回Lists,而不是Options。可能最短的解决方法是:

val pairOpt = for (a <- ao; b <- bo) yield (a+b, b+a*2)
val (x, y) = (pairOpt.map(_._1), pairOpt.map(_._2))

【讨论】:

  • 可能应该提交一个问题以使 unzip 返回与理解一样的可迭代
  • @texasbruce 那么你必须先说服他们Option 应该是Iterable,否则类型不匹配。将隐式转换的Option 返回为Iterable 无论如何都会产生List,因为this
  • 我挖了一点。 Option#unzip 是通过将 Option 隐式转换为 Iterable 来添加的:github.com/scala/scala/blob/v2.12.7/src/library/scala/…option2Iterable。 Option下的很多方法如groupBy, partition都是通过隐式转换添加的。 Option 为某些方法提供专门的方法,例如 map, collect 仅。他们还不如继承 Iterable trait imo
  • NVM 我刚刚看到你的链接。这对我来说是新的。由于转换开销,现在我需要在使用 Option 之前三思而后行。
  • 来自 @texasbruce 的 PR 将正确的 Option#unzip 添加到 Scala 2.13:github.com/scala/scala/pull/7360
【解决方案2】:

模式匹配不是处理选项的最佳方式吗?

val res = for (a <- ao; b <- bo) yield (a+b, b+a*2)

val (x, y) = res match {
  case Some((x, y)) => (Some(x), Some(y))
  case None => (None, None)
}

为什么不被认为是“优雅”?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-23
    • 2021-07-18
    • 2018-05-24
    相关资源
    最近更新 更多