如何将函数转换为函数返回函数返回?

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代码.你会建议什么?

Tra*_*own 9

任何时候你想要在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.


whe*_*ies 4

我会写这样的形式:

 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好多了。

更新:如果您只想处理正确的投影,那么只需返回正确的投影即可。现在它组成了。