In Scala, is there a pre-existing library function for converting exceptions to Options?

StackOverflow https://stackoverflow.com/questions/8013435

  •  21-02-2021
  •  | 
  •  

Question

This is basically to wrap java factory methods which throw exceptions if the item can't be created based on the inputs. I'm looking for something in the base library like:

 def exceptionToOption[A](f: => A):Option[A] ={
    try{
      Some(f)}
    catch{
      case e:Exception => None}
  }

Usage:

val id:Option[UUID] = exceptionToOption(UUID.fromString("this will produce None"))

I know I can write my own but I want to check I am not re-inventing the wheel.

Was it helpful?

Solution

Use scala.util.control.Exception:

import scala.util.control.Exception._

allCatch opt f

And you can make it more sophisticated. For example, to catch only arithmetic exceptions and retrieve the exception:

scala> catching(classOf[ArithmeticException]) either (2 / 0)
res5: Either[Throwable,Int] = Left(java.lang.ArithmeticException: / by zero)

OTHER TIPS

Yes, you can take a look to the scala.util.control.Exception object. Especially, the allCatch function.

As of scala 2.10, you can run your code (e.g. factory method) in a scala.util.Try and then convert it with toOption:

import scala.util.Try
Try("foo".toInt).toOption  // None
Try("7".toInt).toOption    // Some(7)

Or translated to your original example:

val id: Option[UUID] = Try(UUID.fromString("this will produce None")).toOption

Scalaz provides Validation[+E, +A] which is similar to Either.

val result: Validation[Throwable, Something] = ...

result match {
  case Success(x) => ...
  case Failure(x) => ...
}

I use a pattern based on signaling and non-signally NaNs in modern computers. NaN means non-a-number. Division by zero (fp) creates a NaN. sNaNs throw exceptions, non-signaling NaNs are just provided as a result, any future computation on the result also generates a NaN. Evaluate is signalling, TryEvaluate is non-signaling.

Here, Ctx=Context[I,R] is a context block that holds the function's input [I], result[R], and an exception. All are Options. The update method on the context is a copy-update. Not a mutating update. The super-trait just evaluates one or more functions, passing the updated context to the next function. The main evaluate function returns the context if an exception is held (skipping the evaluation). Context[I,R] has a function that translates a (I=>R) into a (Context[I,R]=>Context[I,R]). So a normal function can easily be converted into a context based function.

As you can see, there isn't much code. The traits are just in my utility package and can be used with almost no code by the consumer. Using a library adds to much overhead for the work involved.

I use this for all of my parsers. X-Path based parsers just call a sequence of sub-parsers. Hence the evaluate(Seq) method. Note: I dislike methods. I tend to use functions where I can.

Oops, I think I posted garbage the last time. Here is a github reference. https://github.com/tyohDeveloper/acme/tree/master/src/acme/util

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top