Scala DRYing尝试/捕获

vir*_*yes 7 logging scala dry try-catch

我发现自己重复了简单的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")
Run Code Online (Sandbox Code Playgroud)

工作得很好,意图很清楚,但是当我为所有非关键事件做这种尝试/捕获日志记录时,我会寻找一种方法来干掉它.搜索引导我在scala.util.control.Exception上发布这篇SO帖子.很有帮助,但是按照我喜欢的方式制作/使它工作仍然有点困难.用简单的英语我只想说,"抓住一些动作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)
Run Code Online (Sandbox Code Playgroud)

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

catching( ymdFormat.parseDateTime(date) ) either log.info
Run Code Online (Sandbox Code Playgroud)

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

有没有人知道如何使用control.Exception创建这种语法,在哪里可以传入一个记录器函数by-name在catch块中使用?

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

Dan*_*ral 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))
Run Code Online (Sandbox Code Playgroud)

Validation在我看来,Scalaz可以更好地处理这种事情.

  • @virtualeyes - 对于它的价值,你的"黑客"对我来说比丹尼尔的方法更清晰(如果你没有把它称为"捕捉",而是"tryOrLog"或者不表示第一个论证本身就会被抓住). (2认同)