2017-01-29 2 views
1

У меня есть количество интерфейсов, где каждый из результатов Try() возвращает.Scala - объединить число результатов Try()

Например:

def getElements1(id: Guid): Try[Seq[SpecialElement]] //From interface A 
def getElements2(id: Guid): Try[Seq[SpecialElement]] //From interface B 
def getElements3(id: Guid): Try[Seq[SpecialElement]] //From interface C 

Полностью независимая и может не случайно.

Каков наилучший способ «Scala» для конкатенации их вывода относительно случая Failure()?

ответ

2

Вы можете использовать для постижений:

case class SpecialElement(x: Int) 

val x: Try[Seq[SpecialElement]] = Try(List(SpecialElement(1))) 
val y: Try[Seq[SpecialElement]] = Try(List(SpecialElement(2))) 
val z: Try[Seq[SpecialElement]] = Try(List(SpecialElement(3))) 

for { 
    a <- x 
    b <- y 
    c <- z 
} yield a ++ b ++ c 
Success(List(SpecialElement(1), SpecialElement(2), SpecialElement(3))) 

for { 
    a <- x 
    b <- y 
    c <- Try(throw new Exception) 
} yield a ++ b ++ c 
Failure(java.lang.Exception) 
1

Ну ... nicest 'Scala way' зависит от того, что ваши требования?

Итак ... вы следующие 3 def с,

def getElements1(id: Guid): Try[Seq[SE]] 
def getElements2(id: Guid): Try[Seq[SE]] 
def getElements3(id: Guid): Try[Seq[SE]] 

Случай 1 - Результат терпит неудачу, если по крайней мере один из них не удается, и вы получите ошибку только один отказ.

val result: Try[Seq[SE]] = for { 
    emements1 <- getElements1(id) 
    emements2 <- getElements2(id) 
    emements3 <- getElements3(id) 
} yield emements1 ++ emements2 ++ emements3 

Случай 2 - Результат терпит неудачу, если по крайней мере один из них не удается, и вы хотите, чтобы получить ошибку только все неудачи,

def trySeqToEither[T](tryTSeq: Seq[Try[T]]): Either[Seq[Throwable], Seq[T]] = { 
    val accInit: Either[Seq[Throwable], Seq[T]] = Right(Seq.empty[T]) 

    tryTSeq.aggregate(accInit)({ 
    case (Right(seq), Success(t)) => Right(seq :+ t) 
    case (Right(seq), Failure(ex)) => Left(Seq[Throwable](ex)) 
    case (Left(seq), Success(t)) => Left(seq) 
    case (Left(seq), Failure(ex)) => Left(seq :+ ex) 
    }) 
} 

val seqResultEither: Either[Seq[Throwable], Seq[Seq[SE]]] = trySeqToEither(
    Seq(getElements1(id), getElements2(id), getElements3(id)) 
) 

val resultEither: Either[Seq[Throwable], Seq[SE]] = seqResultEither match { 
    case Right(seqResult) => Right(seqResult.flatten) 
    case Left(seqThrowable) => Left(seqThrowable) 
} 

Случай 3 - Результат игнорирует неисправные вычисления

val emementsOption1 = getElements1(id).toOption 
val emementsOption1 = getElements2(id).toOption 
val emementsOption3 = getElements3(id).toOption 

val result: Seq[SE] = Seq[Seq[SE]](emementsOption1, emementsOption2, emementsOption3).flatten 
Смежные вопросы