Scala 的“for comprehension"与期货 [英] Scala's "for comprehension" with futures

查看:23
本文介绍了Scala 的“for comprehension"与期货的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读 Scala Cookbook (http://shop.oreilly.com/product/0636920026914.do)

I am reading through the Scala Cookbook (http://shop.oreilly.com/product/0636920026914.do)

有一个与 Future use 相关的例子,涉及理解.

There is an example related to Future use that involves for comprehension.

到目前为止,我对理解的理解是,当与一个集合一起使用时,它将产生另一个具有相同类型的集合.例如,如果每个 futureX 都是 Future[Int] 类型,那么下面的也应该是 Future[Int] 类型:

So far my understanding about for comprehension is when use with a collection it will produce another collection with the same type. For example, if each futureX is of type Future[Int], the following should also be of type Future[Int]:

for {
   r1 <- future1
   r2 <- future2
   r3 <- future3
} yield (r1+r2+r3)

谁能解释一下在这段代码中使用 <- 时到底发生了什么?我知道如果它是一个生成器,它将通过循环获取每个元素.

Could someone explain me what exactly happening when use <- in this code? I know if it was a generator it will fetch each element by looping.

推荐答案

先来了解一下.很多次回答它,它是对几个一元操作的抽象:mapflatMapwithFilter.当您使用 <- 时,scalac 将此行脱糖为 monadic flatMap:

First about for comprehension. It was answered on SO many many times, that it's an abstraction over a couple of monadic operations: map, flatMap, withFilter. When you use <-, scalac desugars this lines into monadic flatMap:

r <- monadmonad.flatMap(r => ... )

它看起来像一个命令式计算(monad 的全部内容),您将计算结果绑定到 r.并且 yield 部分被脱糖到 map 调用中.结果类型取决于 monad 的类型.

it looks like an imperative computation (what a monad is all about), you bind a computation result to the r. And yield part is desugared into map call. Result type depends on the type of monad's.

Future trait 有一个 flatMapmap 函数,所以我们可以用它来理解.在您的示例中可以将糖化为以下代码:

Future trait has a flatMap and map functions, so we can use for comprehension with it. In your example can be desugared into the following code:

future1.flatMap(r1 => future2.flatMap(r2 => future3.map(r3 => r1 + r2 + r3) ) )

抛开并行性

不言而喻,如果future2的执行依赖于r1,那么你不能逃避顺序执行,但如果未来的计算是独立的,你有两种选择.您可以强制顺序执行,或允许并行执行.你不能强制后者,因为执行上下文会处理这个.

Parallelism aside

It goes without saying that if execution of future2 depends on r1 then you can't escape sequential execution, but if the future computations are independent, you have two choices. You can enforce sequential execution, or allow for parallel execution. You can't enforce the latter, as the execution context will handle this.

val res = for {
   r1 <- computationReturningFuture1(...)
   r2 <- computationReturningFuture2(...)
   r3 <- computationReturningFuture3(...)
} yield (r1+r2+r3)

将始终按顺序运行.可以通过脱糖轻松解释,之后后续的 computationReturningFutureX 调用仅在 flatMap 内部调用,即

will always run sequentially. It can be easily explained by the desugaring, after which the subsequent computationReturningFutureX calls are only invoked inside of the flatMaps, i.e.

computationReturningFuture1(...).flatMap(r1 => 
    computationReturningFuture2(...).flatMap(r2 => 
        computationReturningFuture3(...).map(r3 => r1 + r2 + r3) ) )

然而,这能够并行运行并且 for comprehension 聚合结果:

However this is able to run in parallel and the for comprehension aggregates the results:

val future1 = computationReturningFuture1(...)
val future2 = computationReturningFuture2(...)
val future3 = computationReturningFuture3(...)

val res = for {
   r1 <- future1
   r2 <- future2
   r3 <- future3
} yield (r1+r2+r3)

这篇关于Scala 的“for comprehension"与期货的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆