斯卡拉(Scala)的“理解力"与期货 [英] Scala's "for comprehension" with futures

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

问题描述

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

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

有一个涉及未来使用的示例,涉及到理解.

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.

推荐答案

首先要理解.回答了很多次,这是对几个monadic操作的抽象:mapflatMapwithFilter.当您使用<-时,scalac会减掉此行,变成单声道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 <- monad转换为monad.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特征具有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,那么您就无法避免顺序执行,但是如果将来的计算是独立的,则有两种选择.您可以强制执行顺序执行,或者执行 allow 进行并行执行.您不能强制使用后者,因为执行上下文将对此进行处理.

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)的“理解力"与期货的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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