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

Hag*_*gai 7 scala

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

我想检查两者是否成功,或者其中一个是否失败,但避免代码重复.就像是:

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

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

知道如何使这项工作优雅吗?

Kar*_*ldt 6

你可以把它转换成Try[MyClass]这样的:

val myclass = for {
  v1 <- t1
  v2 <- t2
} yield new MyClass(v1, v2)
Run Code Online (Sandbox Code Playgroud)

如果t1失败,或两者t1t2失败,myclass将是一个FailureExceptiont1.如果只是t2失败了,myclass将是一个FailureExceptionfor t2.否则,myclass将是一个Success.然后你可以使用recover或者其他方式正常处理它.


Oli*_*ain 5

您可以对这种情况进行尾递归调用(_, 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)
  }
Run Code Online (Sandbox Code Playgroud)

可以让你优雅地做到这一点。对于任何F[_]: TraverseG[_]: Applicative,它定义了 的等价物Future.sequence

def sequence(fa: F[G[A]]): G[F[A]]
Run Code Online (Sandbox Code Playgroud)

该库还为 Try 提供了开箱即用的实例。进一步阅读遍历文档


Ale*_*nov 5

您可以提取本地方法:

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)
}
Run Code Online (Sandbox Code Playgroud)

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