2017-01-29 2 views
1

Ich habe die Anzahl der Schnittstellen, wo jeder der Ergebnisse Try() ergibt.Scala - Verkettung der Anzahl der Try() Ergebnisse

Zum Beispiel:

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 

Die alle unabhängig und kann zufällig fehlschlagen.

Was ist die schönste "Scala" Möglichkeit, ihre Ausgabe in Bezug auf Failure() Fall auch zu verketten?

Antwort

2

können Sie für Comprehensions verwenden:

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

Nun ... nicest 'Scala way' hängt davon ab, was Ihre Anforderungen sind?

So ... Sie haben folgende 3 def s,

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

Fall 1 - Das Ergebnis ausfällt, wenn mindestens 1 von ihnen ausfällt und Sie erhalten den Fehler von nur 1 Versagen.

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

Fall 2 - Das Ergebnis ausfällt, wenn mindestens 1 von ihnen ausfällt und Sie den Fehler von nur alle Fehler bekommen,

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) 
} 

Fall 3 - Das Ergebnis der gescheiterten Berechnungen ignoriert

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