I'm new to Scala. I'm studying try-catch block from one of the websites, where I came to know that Scala also provides Try. Both Try and try-catch block performs the work of catching an Exception. Now my question is Scala already had a try-catch block which performed well then why scala introduced Try? What are advantages and use cases of Try over try-catch in Scala?
1 Answers
The purpose of both try {} catch {}
, Try
monad is error handling but Try
is a functional way of error handling with the functional composition available.
Let's say you are writing an API to divide two numbers, which will explode in the middle of running an application when bad data is provided with unexpected results being propagated to clients.
scala> def divisionWithoutErrorHandling(x: Int, y: Int): Int = x / y
divisionWithoutErrorHandling: (x: Int, y: Int)Int
scala> val result = divisionWithoutErrorHandling(1, 0)
java.lang.ArithmeticException: / by zero
at .divisionWithoutErrorHandling(<console>:12)
... 28 elided
try catch ...
is a forced way to handle errors (java way). And if you forget to catch errors (because compiler does not tell you at compile time), you are doomed.
scala> @throws(classOf[Exception]) def divisionWithErrorHandling(x: Int, y: Int): Int = x / y
divisionWithErrorHandling: (x: Int, y: Int)Int
scala> val result = divisionWithErrorHandling(1, 0) // compiler does not tell you about you need to handle errors here.
java.lang.ArithmeticException: / by zero
at .divisionWithErrorHandling(<console>:11)
... 28 elided
scala> val result = try { divisionWithErrorHandling(1, 0) } catch {case e: Exception => 0 }
result: Int = 0
Now, Try
adds a functional way of handling an operation by encapsulating the operation. Since Try[T]
is a return type there is you get a reminder that you need to handle it gracefully in case of failures.
Try[T]
has two results Either Success
or Failure
. When the operation fails, the return type will be of type Failure
otherwise Success[T]
.
scala> def divisionWithFnErrorHandling(x: Int, y: Int): Try[Int] = Try { x/y }
divisionWithFnErrorHandling: (x: Int, y: Int)scala.util.Try[Int]
scala> val result = divisionWithFnErrorHandling(1, 0)
result: scala.util.Try[Int] = Failure(java.lang.ArithmeticException: / by zero)
And also you can chain the operations with Try
,
scala> divisionWithFnErrorHandling(100, 2).map(x => x * 100).map(x => x + 200)
res5: scala.util.Try[Int] = Success(5200)
So, Try[T]
tells clients that the return type is Try[T]
so its clients responsibility how they want to handle errors.
You can also use Either[Throwable, T]
for error handling but it depends how you write an API.

- 30,204
- 14
- 155
- 192