Reputation: 16723
In the following two functions, someF1
will not compile but someF2
will. It's because someF1
is expected to return Future[Int]
but it returns Future[Future[Int]]
because I am using a for
within a for
. I don't face issue in someF2
because I am flattening Future[Future[]]
in someF2
. Is there an equivalent way of flattening results if I use embedded for
or is someF1
a wrong use case of for
and I should use it only to execute Futures
in parallel and not in sequence?
// Start writing your ScalaFiddle code here
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
def someF1:Future[Int] = {
val f1 = Future[Int]{1}
for(i<-f1) yield{
if(i == 0) {
val f2 = Future{2}
for(j<-f2) yield {i+j} //this will make function return Future[Future[Int]]
}
else {
val f3 = Future{3}
for(k<-f3) yield {i+k}//this will make function return Future[Future[Int]]
}
}
}
// Start writing your ScalaFiddle code here
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
def someF2:Future[Int] = {
val f1 = Future[Int]{1}
f1.flatMap{i=> //flatMap will flatten Future[Future[Int]]
if(i == 0) {
val f2 = Future{2}
f2.map(j=> {i+j})
}
else {
val f3 = Future{3}
f3.map(k=>{i+k})
}
}
}
Upvotes: 0
Views: 38
Reputation: 22850
Complementing @jwvh's answer
You can still avoid the sencond future evaluation with the following, more complicated, piece of code:
def someF1:Future[Int] =
for {
i <- Future[Int]{1}
r <- if (i == 0) {
for (j <- Future[Int]{2}) yield i + j
} else {
for (k <- Future[Int]{3}) yield i + k
}
} yield r
Also, I would recommend you to take a look at the documentation of for/yield
Upvotes: 1
Reputation: 51271
The rule is that, with a for
comprehension, the final generator (i.e. <-
) is translated into a map()
call. Every other generator is a flatMap()
call. So, no, you can't achieve what you're after using nested for
. That creates too many map()
calls and not enough flatMap()
calls.
This will work:
def someF1:Future[Int] = {
val f1 = Future[Int]{1}
for {
i <- f1
j <- Future(2)
k <- Future(3)
} yield {
if (i == 0) i+j
else i+k
}
}
But in that case you are launching one more Future
than you actually need.
Upvotes: 2