Why does this list-of-futures to future-of-list transformation compile and work?
for-comprehension, future, scala
Solution
1) Say f is a `Future[T]`, then writing
for {
t <- f
} yield List(t)
will store the result of the Future f in t - therefor t is of type T. The yield turns it into a List[T], and the type of the whole for-comprehension ends up being Future[List[T]]. So the for-comprehension is where you extract your Ts from your `Futures`, do something with them, and put them back in a Future (OK, I'm simplifying a little bit here).
It's equivalent to
f.map(t => List(t))
2) If your Future f contains a Failure, then the for-comprehension will just return this failed Future instead of executing the yield.
As a general note, for-comprehension in Scala is just sugar that can be rewritten with `map, flatMap, filter, foreach`.
Problem
Disclaimer: the code snippet below relates to one of ongoing Coursera courses. Let's consider it's posted just for a learning purpose and should not be used for submitting as a solution for one's homework assignment. As the comment below states, we need to transform a list of Futures to a single Future of a list. More than that, the resulting Future should fail if at least one of input futures failed. I met the following implementation and I don't understand it completely. ``` /** Given a list of futures `fs`, returns the future holding the list of values of all the futures from `fs`. * The returned future is completed only once all of the futures in `fs` have been completed. * The values in the list are in the same order as corresponding futures `fs`. * If any of the futures `fs` fails, the resulting future also fails. */ def all[T](fs: List[Future[T]]): Future[List[T]] = fs.foldRight(Future(Nil:List[T]))((f, fs2) => for { x <- f xs <- fs2 } yield (x::xs)) ``` In particular, I don't understand the next things in it: - Where does `Future[T] -> T` transformation happen? It looks like `xs <- fs2` is the only place we touch initial `Futures`, and each of `xs` type should be `Future[T]` (but somehow it becomes just `T`). - How are failures handled? It looks like the resulting `Future` object does fail when one of the input `Futures` fails.