【问题标题】:Does Scala have anything like a flatYield?Scala 有类似 flatYield 的东西吗?
【发布时间】:2023-03-09 19:05:02
【问题描述】:

here 已经提出了一个类似的问题,但一些回复并没有完全确认如何异步运行原始的“独立”Futures(而不是链式 flatMaps 或用于理解) )。我也很好奇这种情况,有多个链接的 Futures 都“依赖”于原始 Futures 但彼此不依赖。

不管怎样,这就是我正在做的事情:

val f0 = Future { foo() }
val f1 = Future { bar() }
val f01 = for { v0 <- f0; v1 <- f1 } yield (v0, v1)
f01.flatMap { case (v0, v1) =>
  val f2 = Future { baz(v0, v1) }
  val f3 = Future { qux(v0, v1) }
  for { v2 <- f2; v3 <- f3 } yield (v2, v3)
}

这就是我想做的事情:

val f0 = Future { foo() }
val f1 = Future { bar() }
for { v0 <- f0; v1 <- f1 } flatYield {
  val f2 = Future { baz(v0, v1) }
  val f3 = Future { qux(v0, v1) }
  for { v2 <- f2; v3 <- f3 } yield (v2, v3)
}

有什么方法可以做到这一点,而无需先产生原始值,然后再将它们全部写入链接的flatMap 的参数中?

【问题讨论】:

  • 好的,有人填我。为什么不for {v0&lt;-f0; v1&lt;-f1} yield (baz(v0,v1), qux(v0,v1))
  • @jwvh 在您的示例中,bazqux 将按顺序运行(而不是并行运行)。

标签: scala future for-comprehension


【解决方案1】:

它对你有用吗?

val f0 = Future { foo() }
val f1 = Future { bar() }
for { 
  v0 <- f0
  v1 <- f1 
  f2 = Future { baz(v0, v1)}
  f3 = Future { qux(v0, v1)}
  v2 <- f2
  v3 <- f3
} yield (v2, v3)

【讨论】:

  • 哇,是的,完美运行。使代码更清晰。谢谢!
  • 不是说f2和f3不能并行运行吗?
  • 你甚至可以将 f0 和 f1 移到理解中,如果你读到这个:viktorklang.com/blog/Futures-in-Scala-protips-2.html
  • 非常有帮助——我很早就犯了那个“常见错误”。实际上,我已经开始按照您的帖子的建议进行操作了——从Future.successful {} 开始 for-expressions。很高兴知道它至少有一点先例。
【解决方案2】:

另一种稍微简化代码的方法是使用Futurezip方法:

for { 
  (v0, v1) <- Future { foo() } zip Future { bar() }
  r <- Future { baz(v0, v1) } zip Future { qux(v0, v1) }
} yield r

要更多Futures 而不是多个zips,您也可以使用Future.sequence

for {
  List(a, b, c, d) <- Future.sequence(List(
    Future { foo1() }, 
    Future { foo2() }, 
    Future { foo3() }, 
    Future { foo4() }
  ))
  /* ... */
} yield ???

在这两种情况下,压缩/排序期货将并行执行(当然取决于ExecutionContext)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-15
    • 2014-09-22
    • 2010-11-29
    • 2020-03-26
    • 2011-10-18
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多