Idiomatic Error Handling with Try
Scala supports error handling patterns available in Java using the throw/try/catch constructs. Look at the method below,
def divide(dividend : Int, divisor : Int) = dividend /divisor
An imperative way of handling errors from calling the above method would be,
try { val q = divide(10, 2) } catch { case e : ArithmeticException => println("Divide by zero not allowed") }
The issue with the above, especially with concurrent code, is the thread in which exception has occurred may be different from the perceived thread in which the exception is handled. Also, the the code is not functional as it lacks referential transparency.
However, with scala.util.Try[T], there is a more idiomatic way of handling exceptions, where the underlying error is encapsulated in the returned result.
def divide(dividend : Int, divisor : Int) = Try(dividend /divisor)
The apply method on the companion object takes a by name parameter, which is only executed within the method and not at use site. The result is Try[Int], which can either be a Success[Int] or Failure[Int]. The calling code would than transform to,
divide(10, 2) match { case Success(q) => println(q) case Failure(t) => t.printStackTrace }
Try, as with other container types like Option, List, Future etc, allows operations to map, flat map, filter etc and may be used in comprehensions. For, example the line below will yield Success(4)
divide(10, 3) map {_ + 1}
Exremtely helpful article, please write more.