Scala: what is the right way to fold a collection of futures?

I have a piece of code that sends broadcast message to a set of actors and collects their responses. Please look at the simplified code:

{
  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(_)
}

Then I noticed that behaviors of lines of code 1 and 2 differ. E.g. there are 4 actors sending Traversable(1) as response, and

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

The results of the first line are different: usually I get List(1, 1, 1, 1), but sometimes List(1, 1, 1) or even List(1, 1). It wasn't surprising for me, because Future.fold is unblocking, so it seems some responses could be missed.

But the second line always yields List of four ones.

Could anyone explain the reason why these kinds of fold differ and which of them is preferable?

Answers


The surprising thing for me in your question is the fact that your first fold (which I find preferable by reason of its conciseness) sometimes seems to operate on a list of three (or two) successfully completed futures.

In the normal scheme of things, you have 3 possible outcomes for a future:

  1. Completed normally
  2. Failed (completed with exception)
  3. Uncompleted

Both of the folds that you give will yield a single future that is uncompleted while all of its component futures are completed, or failed if any future (or the fold operation) fails, or completed if all goes well. (Your sentence Future.fold is unblocking, so it seems some responses could be missed is incorrect.)

I can only think that you have some other code somewhere that is completing futures with no result if a certain timeout is breached.

Apart from that, you have swapped the order of the operands in the fold operation in line 2 (should be yield foldResults(xs, x)) so the final order is reversed with respect to line 1.


Need Your Help

How to get ClassLoader from type variable (for parceling a class using generics)

java android generics parcelable

I have a parcelable class with a generic type object. Usually I would read out that object like this:

Can you use a web service as a datasource for a mailmerge

web-services ms-word reporting word-field

Some clients of ours want to use data (SQL Server backend) in a web application we've developed to generate some documents (agreements, contracts, etc). They'd also prefer to have the document tem...