scala模式匹配(试试,尝试)

时间:2017-03-05 15:41:19

标签: scala

我有以下元组 - (t1,t2):(尝试,尝试)

我想检查两者是否成功,或者其中一个是否失败,但是避免代码重复。类似的东西:

.then(function success(response) { //do stuff here}, 
function error(response) {//do stuff here});

当然第二个语句不起作用,因为我需要提供不同的提取变量。但是我必须检查它们,因为我不知道哪个失败并且实际上包含Throwable。 我希望Try会像Future一样行动,所以它会有Try.sequence(t1,t2)。

知道如何优雅地完成这项工作吗?

4 个答案:

答案 0 :(得分:6)

您可以将其转换为Try[MyClass],如下所示:

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

如果t1失败,或者t1t2都失败,myclass将是Failure Exception t1 }}。如果只有t2失败,则myclass将为Failure Exception t2。否则,myclass将是Success。然后,您可以使用recover或其他任何方式正常处理它。

答案 1 :(得分:4)

您可以提取本地方法:

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

我更喜欢OlivierBlanvillain的第一个建议,因为它更容易看到你无法获得无限循环。

答案 2 :(得分:3)

您可以对(_, 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可让您优雅地完成此任务。对于任何F[_]: TraverseG[_]: Applicative,它定义了Future.sequence的等效项:

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

图书馆还提供out of the box instances for Try。进一步阅读traverse documentation

答案 3 :(得分:2)

为什么不使用Scalactic Or and Every而不是使用Try? 所以你可以写这样的东西

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:我没有加入图书馆。