以下の f1~f5 をひとつの Future[Seq[Int]] にしたいとする。
val f1 = Future.successful(1)
val f2 = Future.successful(2)
val f3 = Future.failed(new UnsupportedOperationException("f3"))
val f4 = Future.failed(new UnsupportedOperationException("f4"))
val f5 = Future.successful(5)
val fs = Seq(f1, f2, f3, f4, f5)
scala.concurrent.Future.sequence を使用すると、Failure が含まれていた場合最終的な結果が Failure となる。
val r = Future.sequence(Seq(f1, f2, f3, f4, f5))
r onComplete {
case Success(ns) => println(ns)
case Failure(t) => t.printStackTrace()
}
// java.lang.UnsupportedOperationException: f3
結果が Failure になる要素は除き、Success になる要素のみの Seq を得たい場合、どうするのがいいか。
このような関数を書いてみた。
def sequence[A](f: Future[A]*)(implicit ex: ExecutionContext): Future[Seq[A]] = {
Future.sequence(f.map(_.map(Some(_)).recover { case t => None })).map(_.flatten)
}
これを使うと、欲しい結果は得られた。
val r = sequence(f1, f2, f3, f4, f5)
r onComplete {
case Success(ns) => println(ns)
case Failure(t) => t.printStackTrace()
}
// ArrayBuffer(1, 2, 5)
…が、もっと簡潔な書き方があったり、標準ライブラリにこれを実現する関数が用意されていたりするだろうか?