为什么这份未来清单要对清单的未来转换进行编译和工作



免责声明:下面的代码片段与正在进行的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. 如何处理故障?当其中一个输入Futures失败时,结果Future对象看起来确实失败了

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

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

将把Future f的结果存储在t中,因此t的类型为t。收益率将其转化为List[t],用于理解的整体类型最终为Future[List[t]]。因此,理解的方法是从Futures中提取Ts,用它们做点什么,然后把它们放回未来(好吧,我在这里简化了一点)。

它相当于

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

2) 如果你的Future f包含一个Failure,那么for composition将只返回这个失败的Future,而不是执行yield。

一般来说,Scala中的理解只是糖,可以用map, flatMap, filter, foreach重写。

我是一个会说英语的右撇子,所以通常我向左折叠,但折叠的每一步看起来都像:

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)

请注意,出现故障的版本存在短路。

请参阅ScalaDoc for flatMap以了解这两个信息。

编辑:我说得很谨慎,因为这是Coursera的作品,但更明确地说,这一要求没有得到满足:"返回的未来只有在fs中的所有未来都完成后才能完成。"

最新更新