Scala:折叠一系列期货的正确方法是什么?

时间:2013-12-13 13:51:22

标签: scala future fold

我有一段代码可以向一组演员发送广播消息并收集他们的回复。请查看简化代码:

{
  val responses: Set[Future[T] = // ask a set of actors
  val zeroResult: T
  val foldResults: (T, T) => T

  //1. Future.fold(responses)(zeroResult)(foldResults)
  //2. (future(zeroResult) /: responses) { (acc, f) => for { x <- f; xs <- acc } yield foldResults(x, xs) }
} foreach {
   client ! resp(_)
}

然后我注意到代码行1和行为2的行为不同。例如。有4个演员发送Traversable(1)作为回应,

zeroResult = Traversable.empty[Int]
foldResults = { _ ++ _ }

第一行的结果是不同的:通常我得到列表(1,1,1,1),但有时列表(1,1,1)或甚至列表(1,1)。这对我来说并不奇怪,因为Future.fold是畅通无阻的,所以似乎可能会错过一些回应。

但第二行总是产生四个列表。

有谁可以解释为什么这些折叠不同,哪个更好?

1 个答案:

答案 0 :(得分:0)

在你的问题中,对我来说令人惊讶的是,你的第一个折叠(我觉得它因其简洁而更可取)有时似乎在三个(或两个)成功完成的期货清单上运作。

在正常的计划中,未来有3种可能的结果:

  1. 正常完成
  2. 失败(有例外)
  3. 未完成
  4. 您提供的两个折叠都会产生一个未完成的未来,而其所有组件期货都已完成,或者如果未来(或折叠操作)失败则会失败,或者如果一切顺利,则会完成。 (你的句子Future.fold is unblocking, so it seems some responses could be missed不正确。)

    我只能认为你的某些其他代码正在完成未来,如果某个超时被破坏就没有结果。

    除此之外,你已经在第2行的折叠操作中交换了操作数的顺序(应该是yield foldResults(xs, x)),所以最后的顺序与第1行相反。