首先关于理解。它被多次回答,它是对几个单子操作的抽象:map
, flatMap
, withFilter
. 当您使用时<-
,scalac 将这行脱糖成 monadic flatMap
:
r <- monad
进入monad.flatMap(r => ... )
它看起来像一个命令式计算(monad 的全部内容),你将计算结果绑定到r
. yield
部分被脱糖map
调用。结果类型取决于monad
's 的类型。
Future
trait 有一个flatMap
andmap
函数,所以我们可以用它来理解。在您的示例中,可以将其脱糖为以下代码:
future1.flatMap(r1 => future2.flatMap(r2 => future3.map(r3 => r1 + r2 + r3) ) )
抛开并行
不言而喻,如果执行future2
依赖于r1
然后你不能逃避顺序执行,但如果未来的计算是独立的,你有两个选择。您可以强制执行顺序执行,或允许并行执行。您不能强制执行后者,因为执行上下文将处理此问题。
val res = for {
r1 <- computationReturningFuture1(...)
r2 <- computationReturningFuture2(...)
r3 <- computationReturningFuture3(...)
} yield (r1+r2+r3)
将始终按顺序运行。脱糖可以很容易地解释,之后的后续computationReturningFutureX
调用仅在 flatMaps 内部调用,即
computationReturningFuture1(...).flatMap(r1 =>
computationReturningFuture2(...).flatMap(r2 =>
computationReturningFuture3(...).map(r3 => r1 + r2 + r3) ) )
然而,这能够并行运行,并且 for comprehension 聚合结果:
val future1 = computationReturningFuture1(...)
val future2 = computationReturningFuture2(...)
val future3 = computationReturningFuture3(...)
val res = for {
r1 <- future1
r2 <- future2
r3 <- future3
} yield (r1+r2+r3)