Scala 有类似 flatYield 的东西吗?

Does Scala have anything like a flatYield?

类似的问题已经被问到 here,但是一些回复没有完全承认如何 运行 原始的,"independent" Futures 异步(而不是链式 flatMaps 或理解)。我也很好奇有多个链式 Future 的情况,它们都是 "dependent" 在原始 Future 上但不是彼此。

无论如何,这就是我正在做的事情:

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 的参数中再次写出它们?

对你有用吗?

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)

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

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

要获得更多 Future 而不是多个 zip,您还可以使用 Future.sequence:

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

在这两种情况下 zipped/sequenced 期货将并行执行(当然取决于 ExecutionContext)。