也许不像您希望的那么简单,但这有效:
def flatten[T](xs: Seq[Try[T]]): Try[Seq[T]] = {
val (ss: Seq[Success[T]]@unchecked, fs: Seq[Failure[T]]@unchecked) =
xs.partition(_.isSuccess)
if (fs.isEmpty) Success(ss map (_.get))
else Failure[Seq[T]](fs(0).exception) // Only keep the first failure
}
val xs = List(1,2,3,4,5,6)
val ys = List(1,2,3,5,6)
println(flatten(map(xs))) // Failure(java.lang.Exception: failed)
println(flatten(map(ys))) // Success(List(1, 2, 3, 5, 6))
partition
请注意,正如注释所证明的那样,使用的类型并不安全@unchecked
。在这方面,foldLeft
累积两个序列Seq[Success[T]]
的aSeq[Failure[T]]
会更好。
如果你想保留所有的失败,你可以使用这个:
def flatten2[T](xs: Seq[Try[T]]): Either[Seq[T], Seq[Throwable]] = {
val (ss: Seq[Success[T]]@unchecked, fs: Seq[Failure[T]]@unchecked) =
xs.partition(_.isSuccess)
if (fs.isEmpty) Left(ss map (_.get))
else Right(fs map (_.exception))
}
val zs = List(1,4,2,3,4,5,6)
println(flatten2(map(xs))) // Right(List(java.lang.Exception: failed))
println(flatten2(map(ys))) // Left(List(1, 2, 3, 5, 6))
println(flatten2(map(zs))) // Right(List(java.lang.Exception: failed,
// java.lang.Exception: failed))