Scala干燥尝试/捕获
我发现自己在重复简单的try/catch块,在我看来,这些块应该是一行的 例如,假设我需要将yyyymmdd格式的uri字符串日期转换为Joda时间。对于标准的try/catch块,转换方法如下所示:Scala干燥尝试/捕获,scala,logging,try-catch,dry,Scala,Logging,Try Catch,Dry,我发现自己在重复简单的try/catch块,在我看来,这些块应该是一行的 例如,假设我需要将yyyymmdd格式的uri字符串日期转换为Joda时间。对于标准的try/catch块,转换方法如下所示: def ymd2Date(ymd: Option[String]) = ymd match { case Some(date) => try { Right( ymdFormat.parseDateTime(date) ) } catch { case e =>
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上找到了这个。这很有帮助,但要按我希望的方式去做还是有点困难。简单地说,我只想说,“捕获一些操作获取结果日志错误类型”
因此,我根据control.Exception的一部分对此进行了破解,我感兴趣(或理解为有用):
然后使用以下方法代替try/catch:
catching( ymdFormat.parseDateTime(date) ) either log.info
可以添加选项、msg前缀等,但是……最好找到一种获得控制权的方法。例外情况可以像上面那样工作,因为TypeSafe团队将产生比我想象的更好的代码世界
有人知道如何使用control.Exception创建这种语法吗?在这种情况下,可以按名称传入要在catch块中使用的记录器函数
如果control.Exception有一个“用例”,那就太好了,但我感觉这个实用程序适用于更高级的Scala开发人员一个简单的例子:
import scala.util.control.Exception._
def throwingStuff {
throw new Exception("Hello World!")
}
catching(classOf[Exception]).withApply{err => println(err.toString); None}.apply(Some(throwingStuff))
您可以使用
with apply
来重写Catch
类的应用程序逻辑,以执行诸如写入日志之类的操作。这应该是您想要的:
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))
但是在我看来,Scalaz
验证更好地处理这类东西。为什么要使用呢?如果你要在左
中输入的是无
,那么你似乎可以使用选项[T]
。好的一点,我想把结果折叠起来,或者看起来像是一个自然的匹配…也就是说,目前没有选项折叠,或者至少没有内置到语言中。返回类型对此不太合适withApply
将Throwable
转换为返回值,因此您永远不会得到Left
,而Right
的类型将是Any
或AnyRef
。是的,在您的评论之前实现并编辑!不过,使用Some
是个好主意。需要保留类型。如果我选择了选项[T],类型会被保留/访问吗?是的-应用(一些(throwingsuff))
会像Daniel的答案一样工作。hmmm,类型在两种情况下都需要保留,无论是和选项。在我给出的示例中,我之所以使用,是因为我想将结果与选项match Some/None或getOrElse进行比较。无论如何,两者都需要在类型保存方面加以考虑。我会看看什么样的类型会回来……对,我还没有冒险沿着Scalaz街走,只是在Scala里把脚弄湿了。最基本形式的验证看起来像两者之一,但随后曲线会迅速上升。这是在做…这是相当酷,顺便说一句,看起来我可以放弃我的黑客和采取的方法,其他人,而不是我自己会理解;-)@virtualeyes-无论如何,我觉得你的“黑客”比丹尼尔的方法更清楚(如果你不称它为catching
,而是tryOrLog
,或者不表示第一个参数本身会被捕获的东西,那就更清楚了)。@Rex,“catching”只是遵循控制。例外约定。我曾经也是一名投手,所以我想我喜欢接球手,或者至少喜欢打接球;-)tryOrLog在语义上确实更清晰。。。
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))