sumitsu
sumitsu

Reputation: 1511

Scala: idiomatic Try-match and avoiding catching Throwable

In Scala, a typical use of pattern matching for exception handling (at least per sources like this and this) looks like the following:

Try(...) match {
  case Success(_) => println("success")
  case Failure(exc) => println(s"caught: $exc")
}

However, that pattern also catches any non-Exception Throwables thrown in the try block:

Try(throw new AssertionError("assertion error")) match {
  case Success(_) => println("success")
  case Failure(exc) => println(s"caught: $exc")
}

caught: java.lang.AssertionError: assertion error

In Java, at least, catching Throwable without a compelling reason to do so is generally considered to be an anti-pattern. (This source offers the same counsel for Scala.)

One option to avoid silently catching Throwable is to catch it and re-throw it:

Try(throw new AssertionError("assertion error")) match {
  case Success(_) => println("success")
  case Failure(exc : Exception) => println(s"caught: $exc")
  case Failure(th) => throw th
}

It seems odd, though, that an extra re-throw is necessary to avoid catching non-Exception Throwables (usually considered unrecoverable), and that letting such Throwables escape, implicit in Java-style try/catch syntax, must be implemented explicitly.

Is there a more succinct / idiomatic syntax for using pattern-matching for exception-handling in Scala, while avoiding inadvertently catching Throwable?

Upvotes: 4

Views: 12210

Answers (1)

jwvh
jwvh

Reputation: 51271

Because the recover() method takes a PartialFunction, it can be used to filter for the type of Throwable you want to handle. After that, you can let get unwrap the Try and retrieve a value if it was either a Success or a handled Failure, or it will re-throw if it's still a Failure, i.e. not handled by recover().

val result = Try{
               //code block here
             }.recover{
               case exc:Exception => ... //should return same type as Success
             }.get //unwrap the Try, will throw if Throwable was not an Exception

Upvotes: 10

Related Questions