假设我有一个可能抛出异常的函数f: Int => String
。我想编写一个函数tryF(f: Int => String, arg: Int, defaultOpt: Option[String])
,其工作原理如下:
f(arg)
并返回结果,如果它没有抛出异常defaultOpt.isDefined
则返回defaultOpt.get
我写的如下:
def tryF(f: Int => String, arg: Int, defaultOpt: Option[String]) = {
val r = scala.util.Try(f(arg))
r.toOption orElse defaultOpt getOrElse r.get
}
有意义吗?你会改写吗?
答案 0 :(得分:5)
你的解决方案很好,即使我个人觉得它不太可读。我会做那样的事情:
def tryF[A](f: =>A, defaultOpt: Option[A]): A = (Try(f), defaultOpt) match {
case (Success(result), _) => result
case (Failure(_), Some(defValue)) => defValue
case (Failure(t), None) => throw t
}
请注意,它是不必要的冗长(我可能在某些情况下使用了通配符),但我认为您的用例值得一些自我记录代码。很容易理解触发每种情况的原因。
答案 1 :(得分:2)
一种冗长但易于理解的方式......
import scala.util.{Try,Success,Falure}
def tryF(f: Int => String, arg: Int, defaultOpt: Option[String]) = {
Try(f(arg)) match {
case Success(r) => r
case Failure(ex) => defaultOpt match {
case Some(content) => content
case None => throw ex
}
}
稍微紧凑的方式:
import scala.util.{Try,Success,Falure}
def tryF(f: Int => String, arg: Int, defaultOpt: Option[String]) =
Try(f(arg)) match {
case Success(r) => r
case Failure(ex) => defaultOpt getOrElse {throw ex}
}
答案 2 :(得分:2)
在您的情况下无需Try
; try
/ catch
就够了:
def tryF(f: Int => String, arg: Int, defaultOpt: Option[String]) = {
try {
f(arg)
} catch {
case e: Exception => defaultOpt getOrElse { throw e }
}
}
如果您想使用Try
,我建议您利用recover
:
def tryF(f: Int => String, arg: Int, defaultOpt: Option[String]) = {
Try {
f(arg)
}.recover({
case _ if defaultOpt.isDefined => defaultOpt.get
}).get
}
但是,如果这是你的实际功能,我会考虑重写参数类型是通用的,而不是重写实现,只要实现已经有效:
def tryF[A, B](f: A => B, arg: A, defaultOpt: Option[B]): B = /* ... */
答案 3 :(得分:1)
def tryF(f: Int => String, arg: Int, defaultOpt: Option[String]) = {
val r = scala.util.Try(f(arg))
if (r.isSuccess) r.get else defaultOpt.getOrElse(r.get)
// reads like -> if r is success, get from r, else get from default, else get from r
}
答案 4 :(得分:1)
def tryF(f: Int => String, arg: Int, defaultOpt: Option[String]) = {
val r = scala.util.Try(f(arg))
(r, defaultOpt) match {
case (Success(result), _) => result
case (Failure(_), Some(opt)) => opt
case (Failure(ex), None) => throw ex
}