Как преобразовать Seq [Try] в Try [Seq] - PullRequest
0 голосов
/ 24 сентября 2019

С помощью Futures существует простой способ преобразования Seq[Future] в Future[Seq]:

Future.sequence(seqOfFutures)

Я не смог найти аналог с Try.

Он работает с foldLeft, но то, что мне действительно нравится, будет иметь что-то вроде Try.sequence(seqOfTry).

Есть ли причина, по которой такая функция не предоставляется?

Какэто сделано правильно?

Семантика:

A Список значений при Успехе: Success(Seq(1,2,3,4))

Для Отказа есть 2 возможности:

  • Не срабатывает на кулак Failure и возвращает его.Это решается этим вопросом: listtryt-to-trylistt-in-scala

  • Собирает все Failures и возвращает «составной» сбой.

Есть ли также решение для 'составного' отказа ?

Ответы [ 2 ]

3 голосов
/ 24 сентября 2019

Это решение второго вопроса.

case class CompoundError(errs: List[Throwable]) extends Throwable

def toTry[T](list: List[Try[T]]): Try[List[T]] =
  list.partition(_.isSuccess) match {
    case (res, Nil) =>
      Success(res.map(_.get))
    case (_, errs) =>
      Failure(CompoundError(errs.collect { case Failure(e) => e }))
  }

Операция partition разделяет успехи и неудачи, а match возвращает соответствующее значение в зависимости от того, есть ли ошибки или нет.


Предыдущее решение:

case class CompoundError(errs: List[Throwable]) extends Throwable

def toTry[T](list: List[Try[T]]): Try[List[T]] = {
  val (res, errs) = list.foldLeft((List.empty[T], List.empty[Throwable])) {
    case ((res, errs), item) =>
      item match {
        case Success(t) => (t :: res, errs)
        case Failure(e) => (res, e :: errs)
      }
  }

  errs match {
    case Nil => Success(res.reverse)
    case _ => Failure(CompoundError(errs.reverse))
  }
}
3 голосов
/ 24 сентября 2019

Согласно предложению Луиса Validated предназначено для накопления ошибок, поэтому рассмотрим traverse примерно так

la.traverse(_.toEither.toValidatedNec)
lb.traverse(_.toEither.toValidatedNec)

, который выдает

res2: cats.data.ValidatedNec[Throwable,List[Int]] = Invalid(Chain(java.lang.RuntimeException: boom, java.lang.RuntimeException: crash))
res3: cats.data.ValidatedNec[Throwable,List[Int]] = Valid(List(1, 2, 3))

, где

import cats.syntax.traverse._
import cats.instances.list._
import cats.syntax.either._
import scala.util.{Failure, Success, Try}

val la: List[Try[Int]] = List(Success(1), Success(2), Failure(new RuntimeException("boom")), Success(3), Failure(new RuntimeException("crash")))
val lb: List[Try[Int]] = List(Success(1), Success(2), Success(3))

Без накопления ошибок мы могли бы просто упорядочить как

import cats.implicits._
la.sequence 

, который выдает

res0: scala.util.Try[List[Int]] = Failure(java.lang.RuntimeException: boom)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...