Suppose I have a few functions that raise exceptions. I am wrapping them to return Either[Throwable, <function return type>]
. (Let's assume I need Either
rather than 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) }
...
Now I would like to write a generic wrapper to get rid of the bolierpllate code. What would you suggest ?
Any time you want to make something generic with respect to arity, Shapeless is pretty likely to have what you need. In this case you can write the following:
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)
}
)
Now suppose we have an unsafe method like the following:
def bad(s: String, i: Int) = s.toInt / i
We can wrap it:
scala> val better = safeify(bad _)
better: (String, Int) => Either[Throwable,Int] = <function2>
And now we don't have to worry about exceptions:
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")
This will work for any old FunctionN
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With