Mic*_*ael 8 scala exception-handling either
假设我有一些函数可以引发异常.我正在包装他们返回Either[Throwable, <function return type>]
.(假设我需要Either
而不是Try
).
def fooWrapper(arg1: FooArg1, arg2: FooArg2) =
try Right(foo(arg1, arg2)) catch { case NonFatal(e) => Left(e) }
def barWrapper(arg1: BarArg1, arg2: BarArg2, a3: BarArg3) =
try Right(bar(arg1, arg2, artg3)) catch { case NonFatal(e) => Left(e) }
...
Run Code Online (Sandbox Code Playgroud)
现在我想写一个通用的包装器来摆脱bolierpllate代码.你会建议什么?
任何时候你想要在arity方面做一些通用的东西,Shapeless很可能拥有你需要的东西.在这种情况下,您可以编写以下内容:
import scala.util.control.NonFatal
import shapeless._, ops.function._
def safeify[F, A <: HList, R, O](f: F)(implicit
ftp: FnToProduct.Aux[F, A => R],
ffp: FnFromProduct[A => Either[Throwable, R]]
) = ffp((a: A) =>
try Right(ftp(f)(a)) catch {
case NonFatal(ex) => Left(ex)
}
)
Run Code Online (Sandbox Code Playgroud)
现在假设我们有一个不安全的方法,如下所示:
def bad(s: String, i: Int) = s.toInt / i
Run Code Online (Sandbox Code Playgroud)
我们可以包装它:
scala> val better = safeify(bad _)
better: (String, Int) => Either[Throwable,Int] = <function2>
Run Code Online (Sandbox Code Playgroud)
现在我们不必担心例外情况:
scala> better("1", 0)
res0: Either[Throwable,Int] = Left(ArithmeticException: / by zero)
scala> better("a", 1)
res1: Either[Throwable,Int] = Left(NumberFormatException: For input string: "a")
Run Code Online (Sandbox Code Playgroud)
这适用于任何旧的FunctionN
.
我会写这样的形式:
def wrap[Value](f: => Value): Either[Value, Exception] = try{
Right(f).right
}
catch{
case ex: Exception => Left(ex).right
}
def foo(arg1: FooArg1, arg2: FooArg2) = wrap{
//anything I'd have written before in foo
}
Run Code Online (Sandbox Code Playgroud)
但这不构成。Try
好多了。
更新:如果您只想处理正确的投影,那么只需返回正确的投影即可。现在它组成了。