2017-03-05 18 views
6

mam następujące Tuple - (t1, t2): (próbować, próbować)scala wzorzec dopasowania na (próbować, próbować)

Chcę sprawdzić, czy oba udało lub jeśli jeden z nich nie udało, ale należy unikać duplikacja kodu. Coś jak:

(t1,t2) match { 
case (Success(v1),Success(v2)) => new MyClass(v1,v2) 
case (Failure(e),_) | (_,Failure(e)) => println(e.getMessage) 
} 

Oczywiście drugie oświadczenie nie będzie działać, ponieważ muszę podać różne zmienne ekstrakcji. ale muszę je sprawdzić, ponieważ nie wiem, które zawiodły i faktycznie zawierają Throwable. Chciałbym, aby Try działał jak Future, więc będzie miał Try.sequence (t1, t2).

Każdy pomysł, jak to zrobić elegancko?

Odpowiedz

3

Można zrobić ogon rekurencyjnej wezwanie do wypadku (_, Failure(e)):

@annotation.tailrec 
def apply(t1: Try[Any], t2: Try[Any]): Any = 
    (t1, t2) match { 
    case (Success(v1), Success(v2)) => new MyClass(v1,v2) 
    case (Failure(e), _) => println(e.getMessage) 
    case _ => apply(t2, t1) 
    } 

Cats pozwala to zrobić elegancko. Dla każdego F[_]: Traverse i G[_]: Applicative, definiuje equivalant z Future.sequence:

def sequence(fa: F[G[A]]): G[F[A]] 

Biblioteka udostępnia również out of the box instances for Try. Dalsze czytanie w traverse documentation.

+0

niesamowita biblioteka, dzięki! – Raytracer

4

Można wyodrębnić lokalną metodę:

def onFail(e: Throwable) = println(e.getMessage) 

(t1,t2) match { 
    case (Success(v1),Success(v2)) => new MyClass(v1,v2) 
    case (Failure(e),_) => onFail(e) 
    case (_,Failure(e)) => onFail(e) 
} 

wolałbym go do pierwszego sugestią OlivierBlanvillain po prostu dlatego, że łatwiej jest zobaczyć nie można uzyskać nieskończoną pętlę.

2

Zamiast używać Spróbuj, dlaczego nie używać Scalactic Or and Every? Więc można napisać coś jak ten

val o1 = Or.from(t1) 
val o2 = Or.from(t2) 
withGood(o1, o2){(x, y) => { 
    //do what you want to do if both are good (or Success in Try) 
}}.recover{ 
    //do what you want to do if either one is bad (or Failure in Try) 
} 

PS: Nie jestem związany z biblioteką.

6

można przekonwertować go do Try[MyClass] tak:

val myclass = for { 
    v1 <- t1 
    v2 <- t2 
} yield new MyClass(v1, v2) 

Jeśli t1 zawiodły, albo oba t1 i t2 zawiodły, myclass będzie Failure z Exception dla t1. Jeśli tylko t2 nie powiedzie się, myclass będzie Failure z Exception dla t2. W przeciwnym razie myclass będzie Success. Następnie można przetworzyć go normalnie za pomocą recover lub cokolwiek innego.