以下の 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)
…が、もっと簡潔な書き方があったり、標準ライブラリにこれを実現する関数が用意されていたりするだろうか?