为什么这个未来的列表转换列表编译和工作?

时间:2013-12-01 00:05:11

标签: scala future for-comprehension

免责声明:以下代码段与正在进行的Coursera课程之一相关。 我们认为它只是出于学习目的而发布,不应该用于提交作为家庭作业的解决方案。

正如下面的评论所述,我们需要将Futures列表转换为列表的单个Future。更重要的是,如果至少有一个输入期货失败,那么最终的未来就会失败。

我遇到了以下实施,我完全不明白。

/** 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))

特别是,我不了解其中的下一步:

  1. Future[T] -> T转换发生在哪里?看起来xs <- fs2是我们触及初始Futures的唯一地方,xs类型中的每一个都应为Future[T](但不知何故,它变为T)。
  2. 如何处理失败?当其中一个输入Future失败时,看起来生成的Futures对象会失败。

2 个答案:

答案 0 :(得分:6)

1)假设f是Future[T],然后写

for {
 t <- f
}  yield List(t)

将Future f的结果存储在t中 - 因此t为T类型。yield将其转换为List [T],整个for-comprehension的类型最终为Future [List [T] ]。因此,理解是从Futures中提取你的Ts,用它们做一些事情,然后把它们放回未来(好的,我在这里简化一点)。

相当于

f.map(t => List(t))

2)如果你的未来f包含失败,那么for-comprehension将只返回失败的Future而不是执行yield。

总的来说,Scala中的for-comprehension只是可以用map, flatMap, filter, foreach重写的糖。

答案 1 :(得分:2)

我是说英语的右撇子,所以通常我会弃左,但折叠的每一步都是这样的:

Fn flatMap ((x: T) => Fs map (xs => x :: xs))

您的值为x

该功能适用​​于成功,这解释了为什么失败会让你感到寒冷:

scala> timed(Await.ready(all(List(Future{Thread sleep 5*1000; 1},Future(2),Future{Thread sleep 10*1000; 3})), Duration.Inf))
res0: (Long, scala.concurrent.Awaitable[List[Int]]) = (10002419021,scala.concurrent.impl.Promise$DefaultPromise@2a8025a0)

scala> timed(Await.ready(all(List(Future{Thread sleep 5*1000; 1},Future(???),Future{Thread sleep 10*1000; 3})), Duration.Inf))
res1: (Long, scala.concurrent.Awaitable[List[Int]]) = (5000880298,scala.concurrent.impl.Promise$DefaultPromise@3750d517)

请注意,故障版本会短路。

有关这两位信息,请参阅有关flatMap的ScalaDoc。

编辑:我说的很谨慎,因为这是Coursera的工作,但更明显的是,这个要求没有得到满足:“只有在fs的所有期货都已完成后,才会完成返回的未来。”