2013-12-13 15 views
4

我有一段代碼向一組角色發送廣播消息並收集他們的響應。請看簡化代碼:斯卡拉:摺疊一系列期貨的正確方法是什麼?

{ 
    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正在暢通無阻,所以看起來有些反應可能會被忽略。

但第二行總是產生四個列表。

任何人都可以解釋這種摺疊不同的原因,哪些更好?

+0

是對摺的原因收集所有回覆?如果是這樣,我建議只使用Future.sequence將響應未來列表轉換爲響應列表的未來,當所有響應都已失敗或失敗時將完成響應列表 –

回答

0

對我來說,在你的問題中令人驚訝的事情是,你的第一個摺疊(我認爲它的簡潔性更好)有時似乎在三個(或兩個)成功完成的期貨清單上操作。

在事情發展的正常方式,你有一個未來3個可能的結果:

  1. 正常完成
  2. 失敗(有例外完成)
  3. 未完成

兩者的如果任何未來的(或摺疊操作)失敗,或者如果所有的未來都完成,那麼您給出的摺疊將會產生一個未完成的單一未來,埃爾。 (你的句子Future.fold is unblocking, so it seems some responses could be missed是不正確的。)

我只能認爲你有一些其他的代碼在某個地方完成了期貨,沒有結果,如果某個超時被破壞。

除此之外,你換入2號線在摺疊操作的操作數的順序(應該是yield foldResults(xs, x)),所以最終的順序相對於反轉線路1