什么是惯用的scala方法,可以为Try实例中包含的抛出异常添加更多细节

时间:2015-01-16 10:18:29

标签: scala exception-handling idiomatic

例如

def shouldThrow:String = throw new RuntimeException("exception1")
def shouldThrowButWithContextDetails(detail:String):Try[String] = {
     val ex = Try{shouldThrow}
      if(ex.isFailure)
          Failure(new RuntimeException(s"Error in context: $detail",ex.failed.get))
      else
         ex
}
shouldThrowButWithContextDetails("detail1")
//should throw new RuntimeException(s"Error in context: detail1",and the cause))

在scala中做这样的事情是否有意义?

4 个答案:

答案 0 :(得分:1)

不是使用ExceptionTry中的所有内容进行编码,而是最好使用Either(更好的是,Scalaz \/),然后你可以在左侧(失败)方面拥有除例外之外的其他东西。您可以使用scala.util.control.Exception来捕获Either s中的例外:

import scala.util.control.Exception._
def shouldThrowButWithContextDetails(detail:String)
  : Either[(Exception, String), String] = {
  val ex: Either[Exception, String] = allCatch either shouldThrow
  ex.left.map { failure => (failure, s"Error in context: $detail") }
}

然后Left(失败)案例具有适当的类型(Execption, String),您可以以适当的方式处理,而不是试图在Exception中走私额外的数据。

答案 1 :(得分:1)

到目前为止,我发现的最简单的方法是这种方法

def shouldThrowButWithContextDetails(detail:String):Try[String] =
  Try{shouldThrow}.transform(
    x=>Success(x),
    f=>Failure(new RuntimeException(s"Error in context: $detail",f)))

答案 2 :(得分:1)

使用recoverWith是否合适?

def shouldThrowButWithContextDetails(detail:String):Try[String] = 
    Try{shouldThrow}.recoverWith{
        case ex:Throable=> Failure(new RuntimeException(s"Error in context: $detail",ex))}

答案 3 :(得分:0)

将这样的上下文信息包装起来是完全正常的。

然而,如果意图是最终应该抛出异常,那么你就不需要坚持尝试。使用匹配来分离失败与成功相比要简单得多。这是我看到它最常用的方式:

def shouldThrowButWithContextDetails(detail:String): String = {
    Try {shouldThrow} match {
        case Success(s) => s
        case Failure(e) =>
          throw new RuntimeException(s"Error in context: $detail", e)
    }
}