融合Scala中的执行流和异常流

时间:2015-02-07 17:30:10

标签: scala

我使用以下命令包装布尔函数并返回其成功状态:

  def wrapper(wrapped: => Boolean) : Boolean = { // this form of prototype takes a function by name
    try {
      return wrapped 
    } catch { 
        case anyException : Throwable => 
        log(anyException.toString)
        return false }
  } 

基本原理是wrapper函数应返回整体二进制状态,无论wrapped函数是否未能捕获其自身的意外异常并执行相同操作。因此wrapper通过其布尔返回值传达成功和失败。对于函数结果数据,它也可以是Option,而不是布尔值。

如何在Scala中以其他更好的方式实现这一目标?

我注意到这个代码的一个基本原理(少数其他的),无可否认的是,try catch块在流控制块中很麻烦。另一个原因是我倾向于在我的项目的某个区域中使用这种模式。

2 个答案:

答案 0 :(得分:2)

您可以使用Try。虽然它只会捕获NonFata(scala.util.control.NonFatal),但在大多数情况下,这就是你想要的。

import scala.util.Try
def wrapper(predicate: => Boolean) : Boolean = {
  Try(predicate) getOrElse false
}

或者另一种方式(例如,如果你真的想抓住任何Throwable)

import scala.util.control.Exception._
def wrapper(predicate: => Boolean) : Boolean = {
  catching(classOf[Throwable]) opt predicate getOrElse false
}

答案 1 :(得分:1)

Scala提供了Try功能,可以在这种情况下使用。

请注意,保留当前的包装器可能会导致多个错误。当您收到 false 结果时,您无法知道它是来自应用程序异常还是来自简单的错误评估。因此,您无法正确处理系统中的任何异常,这可能会导致多个不一致。此外,当你得到一个 false 结果时,你的应用程序内部状态可能会被认为是未知的,因此查看该框以了解该猫是死了还是活着是非常困难的。

要解决此问题,scala的Try功能将为您处理这些可能的状态,在您的情况下返回 - 成功(elem:Boolean),以防您的谓词有效执行,并且如果在执行期间抛出异常,则失败(例如:Throwable)。然后,您可以使用模式匹配来找出是哪种情况:

import scala.util.{Try, Success, Failure}
[...]
Try(predicate) match {
  case Success(bool) => bool
  case Failure(ex) => /* Do something to handle ex */
}

这在某种程度上消除了你的包装的需要,因为你可以保持Try的结果然后匹配它或者在你需要的时候得到它的结果。而且,正如之前的答案所示,您可以使用一套相当完整的操作来以更时尚的方式处理所有这些情况。