Reputation: 20182
I have been looking at this How are Scala Futures chained together with flatMap? and the corresponding article as well on translating for comprehension. I am slowly adding stuff to my for comprehension and am stuck as I guess the code I thought would translate to is not correct.
Here I have a runProgram and runProgram2 which I thought would be equivalent and are not because runProgram2 does not compile. Can someone explain the equiavalent of this for comprehension...
NOTE: yes I know that future.flatMap is typically for collapsing Future[Future[String]] but this is a trimmed down version of my file(perhaps I trimmed it down too far).
def main(args: Array[String]) = {
val future1: Future[String] = runMyProgram()
//val future2: Future[String] = runMyProgram2()
}
def runMyProgram() : Future[String] = {
val future = serviceCall()
future.flatMap(processAllReturnCodes)
}
// def runMyProgram2() : Future[String] = {
// val future = serviceCall()
// for {
// result <- future
// } yield processAllReturnCodes(result)
// }
def processAllReturnCodes(count: Int) : Future[String] = {
val promise = Promise.successful("done")
promise.future
}
def serviceCall() : Future[Int] = {
val promise = Promise.successful(5)
promise.future
}
def serviceCall2() : Future[String] = {
val promise = Promise.successful("hithere")
promise.future
}
Upvotes: 0
Views: 352
Reputation: 15773
This for
comprehension:
for {
result <- future
} yield processAllReturnCodes(result)
Is being translated to this:
val t: Future[Future[String]] = future.map(result => processAllReturnCodes(result))
Comprehension is really only syntactic sugar for map
and flatMap
, with flatMap
you can flatten the future nesting:
val u: Future[String] = future.flatMap(result => processAllReturnCodes(result))
The difference lies in the signatures:
def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S]
So map
takes a function form T
to S
and wraps the S
in a future, the problem is that here your S
is a Future[String]
which is wrapped in another future giving Future[Future[String]]
, flatMap
instead:
def flatMap[S](f: T => Future[S])(implicit executor: ExecutionContext): Future[S]
Takes a function from T
to Future[S]
and returns that future, in your case your method already returns a future and it's a valid parameter for flatMap
.
Upvotes: 2