问题描述
我正在阅读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操作的抽象:map
,flatMap
,withFilter
.当您使用<-
时,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
特征具有flatMap
和map
函数,因此我们可以使用它来理解.在您的示例中,可以将其替换为以下代码:
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)的“理解力"与期货的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!