Seq is iterable, isn't it?

The following code works fine:

def awaitFutures[A](futures: Future[A]*)(implicit d: Duration) {
  val p = Promise[Unit]()
  for (_ <- Future.foldLeft(futures.toList)(())((_, _) => ())) p.trySuccess(())
  for (f <- futures; e <- f.failed) p.tryFailure(e)
  Await.result(p.future, d)

But I don’t understand why I need the call to toList on futures. As a Seq[Future[A]] it’s already iterable and thus a suitable argument to foldLeft, is it not? Without the toList call, I get an error:

 found   : Seq[scala.concurrent.Future[A]]
 required: scala.collection.immutable.Iterable[scala.concurrent.Future[?]]
  for (_ <- Future.foldLeft(futures)(())((_, _) => ())) p.trySuccess(())

scala.collection.Seq extends scala.collection.Iterable.
Compiler is looking for a scala.collection.immutable.Iterable

Also, you might find Scalaz’s sequence, traverse, traverseU useful to
accomplish what you want. Most notably, you can use sequence to convert
F[G[A]] => G[F[A]] in general (where F is Traversable and G is Applicative).

Brian Maso

Thanks. I had in my mind that varargs would give me an immutable sequence, but there’s no such guarantee (I read Seq in the error message as an alias for immutable.Seq from Predef, but there is no such thing).

As for not using traverse, I don’t need the F structure in the result, so I was trying to avoid creating it (more as an exercise to myself than anything else).

The reason it can’t is that in Java, varargs uses Array which is mutable.

1 Like

BTW this sort of thing is where Scala Clippy can be handy, I believe it
highlights the problematic parts of a type mismatch. (And if it doesn’t
cover this situation, support can be added.)

1 Like