7

我发现自己在重复简单的 try/catch 块,IMO 应该是 1-liners。

例如,假设我需要将 yyyymmdd 格式的 uri 字符串日期转换为 Joda-Time。使用标准的 try/catch 块,转换方法如下所示:

def ymd2Date(ymd: Option[String]) = ymd match {
  case Some(date) =>
    try { Right( ymdFormat.parseDateTime(date) ) }
    catch { case e => 
      log.info(e.getMessage)
      Left(None) 
    }
  case None => 
    Left(None) // no uri date param
}
val ymdFormat = DateTimeFormat.forPattern("yyyyMMdd")

工作得很好,意图很明确,但是当我对所有非关键事件进行这种尝试/捕获日志记录时,我会寻找一种方法来将其干燥。搜索使我找到了关于 scala.util.control.Exception的 SO 帖子。有帮助,但仍然有点难以摸索/让它以我想要的方式工作。用简单的英语我只想说,“catch some-action get-result log-error-type”。

所以,我根据 control.Exception 我感兴趣的部分破解了这个(或理解为有用):

class Catcher[T](f: => T) {   
  type Logger = (=> Any) => Unit

  def either[T]( logger: => Logger ) = {
    try { Right(f) }
    catch { case e => 
      logger(e.getMessage)
      Left(None)
    }
  }
}
def catching[T](f: => T) = new Catcher(f)

然后像这样代替 try/catch 使用:

catching( ymdFormat.parseDateTime(date) ) either log.info

可以添加选项、msg 前缀等,但是......最好找到一种方法来获得 control.Exception 像上面一样工作,因为 TypeSafe 工作人员将比我更好地生成代码世界永远想象写作。

有谁知道如何使用 control.Exception 创建这种语法,其中可以按名称传入记录器函数以在 catch 块中使用?

如果有 control.Exception 的“用例”会很棒,但我觉得这个实用程序适用于更高级的 Scala 开发人员

4

2 回答 2

7

这应该做你想要的:

import scala.util.control.Exception
def log(logger: => Logger)(e: Throwable) = {
    logger(e.getMessage)
    None
}
Exception.allCatch withApply log(logger) apply Some(ymdFormat.parseDateTime(date))

Validation但在我看来,这种东西最好由 Scalaz 处理。

于 2012-04-11T17:22:21.397 回答
3

一个简单的例子:

import scala.util.control.Exception._

def throwingStuff {
  throw new Exception("Hello World!")
}

catching(classOf[Exception]).withApply{err => println(err.toString); None}.apply(Some(throwingStuff))

您可以使用withApply覆盖类的应用程序逻辑Catch来执行诸如写入日志之类的操作。

于 2012-04-11T17:21:51.763 回答