Published 2014-12-27.
Last modified 2016-01-23.
Time to read: 3 minutes.
Try
is a utility class provided by the Scala runtime library. It either holds the value of a successful computation or it holds an Exception
. The try/catch/finally
language construct is also examined.
The sample code for this lecture can be found in
courseNotes/
.
Try
is a utility class provided by the Scala runtime library.
It either holds the value of a successful computation or it holds a Throwable
,
which is most commonly an Exception
or subclass thereof.
There are two subclasses: Success
and Failure
.
Here is an example:
scala> import scala.util.{Try, Success, Failure} import scala.util.{Try, Success, Failure}
scala> def divide(dividend: Int, divisor: Int): Try[Int] = { | Try(dividend/divisor) match { | case Success(v) => | println(s"Result of $dividend/$divisor is: $v") | Success(v) | case Failure(e) => | println("You must have divided by zero or entered something that’s not an Int.") | println(e.getMessage) | Failure(e) | } | } divide: (dividend: Int, divisor: Int)scala.util.Try[Int]
scala> divide(4, 2) Result of 4/2 is: 2 res0: scala.util.Try[Int] = Success(2)
scala> divide(2, 0) You must have divided by zero or entered something that’s not an Int. / by zero res1: scala.util.Try[Int] = Failure(java.lang.ArithmeticException: / by zero)
It is often useful to initiate multiple tasks and then return a collection of results, some of which may have failures.
To assist you to write this sort of code, you will need a way to manipulate the collections of successes and failures.
The Trying Harder exercise in the Partial Functions lecture of the
Intermediate Scala course shows you several methods of handling collections of Try
.
Try
does not provide the ability to chain clauses with an andThen
combinator.
That is unfortunate, because it would be nice to be able to write code like this.
val x: Try[Int] = Try { 2 / 0 } andThen { case Failure(ex) => println(s"Logging ${ex.getMessage}") } andThen { case Success(value) => println(s"Success: got $value") case Failure(ex) => println(s"This just shows that any failure is provided to each chained andThen clause ${ex.getMessage}") }
The Partial Functions lecture of the
Intermediate Scala course
shows how to enrich Try
with an andThen
combinator.
The code is provided as part of the scalacourses-utils project on GitHub.

Exercise: Yoda He Is
“There is no try. There is only do, or do not.”
This exercise is a fun review of how import aliases work.
Rewrite the above Scala code using the following import:
import scala.util.{Try => _, Success => Do, Failure => DoNot}
Solution
object YodaHeis extends App { import scala.util.{Try => _, Success => Do, Failure => DoNot}
def divide(dividend: Int, divisor: Int): util.Try[Int] = { util.Try(dividend/divisor) match { case Do(v) => println(s"Result of $dividend/$divisor is: $v") Do(v) case DoNot(e) => println("You must have divided by zero or entered something that’s not an Int.") println(s"Error: ${e.getMessage}") DoNot(e) } }
println(s"divide(4, 2)=${divide(4, 2)}") println(s"divide(2, 0)=${divide(2, 0)}") }
NoStackTrace
It is somewhat expensive
to fill in a new Exception
’s stack trace.
Scala offers a way to create a new Exception
that does not contain a stack trace.
An Exception
without a stack trace should not be thrown because it might be difficult to determine the answers to questions like
“who created this Throwable
?” when debugging.
However, this lighter-weight Exception
can be useful to pass around, as we shall see in a moment.
scala> import util.control.NoStackTrace import util.control.NoStackTrace
scala> val e = new Exception("Help!") with NoStackTrace e: Exception with scala.util.control.NoStackTrace = $anon$1: Help!
The above creates an anonymous class, which means an extra class file is created every time the code is executed. These class files will pile up throughout the program’s life cycle in the JVM.
NoStackTrace Improved
We could improve the code by defining a class that mixes NoStackTrace
into Exception
.
We discussed how mixing in traits could change the behavior of a Java or Scala class in the
Scala Traits lecture.
scala> class ExceptTrace(msg: String) extends Exception(msg) with NoStackTrace defined class ExceptTrace
scala> val e2 = new ExceptTrace("Boom!") e2: ExceptTrace = ExceptTrace: Boom!
The above is efficient.
If your exceptions are invariant in all their properties each time,
you could define a singleton object
instead of a class
instance for even greater efficiency.
scala> object TheExceptTrace extends Exception("Boom!") with NoStackTrace defined module TheExceptTrace
try / catch / finally
try
/ catch
/ finally
is a Scala language control structure.
Let’s see it in action.
scala> def divide2(dividend: Int, divisor: Int): Int = { try { dividend/divisor } catch { case e: ArithmeticException => println(e.getMessage) 0 case e: Exception => println(s"Did not see this one coming! $e") 0 } }
def divide2(dividend: Int, divisor: Int): Int
scala> divide2(4, 2) res23: Int = 2
scala> divide2(2, 0) / by zero res24: Int = 0
As you can see, two problem cases are handled: ArithmeticException
and all other Exception
s.
The order that the exceptions are listed is significant.
Each exception case
can return a different value, and can contain nested try
/ catch
clauses and optionally a
finally
clause.
Unlike Java, the finally
clause does not affect the returned value, and is only useful for side effects.
scala> def divide3(dividend: Int, divisor: Int): Int = { try { dividend/divisor } catch { case e: ArithmeticException => println(e.getMessage) 0
case e: Exception => println(s"Did not see this one coming! $e") 0 } finally { println("The end") } }
def divide3(dividend: Int, divisor: Int): Int
scala> divide3(4, 2) res23: Int = 2
scala> divide3(2, 0) / by zero res24: Int = 0
The problem with the code above is that the return value does not indicate if a problem happened.
Instead of returning a 0, it would be better to return the exception.
Let’s create a better program by combining try
/ catch
/ finally
with Try
.
scala> def divide4(dividend: Int, divisor: Int): Try[Int] = { try { Success(dividend/divisor) } catch { case e: Exception => println(e.getMessage) Failure(e) } }
def divide4(dividend: Int, divisor: Int): scala.util.Try[Int]
scala> divide4(4, 2) res20: scala.util.Try[Int] = Success(2)
scala> divide4(2, 0) / by zero res21: scala.util.Try[Int] = Failure(java.lang.ArithmeticException: / by zero)
We can express this more succinctly if we are willing to forego the println
s.
Note the import
statement.
scala> import scala.util.{Try, Success, Failure}
scala> def divide5(dividend: Int, divisor: Int): Try[Int] = Try(dividend/divisor)
def divide5(dividend: Int, divisor: Int): scala.util.Try[Int]
scala> divide5(4, 2) res20: scala.util.Try[Int] = Success(2)
scala> divide5(2, 0) / by zero res21: scala.util.Try[Int] = Failure(java.lang.ArithmeticException: / by zero)
Simple, short, robust code!
© Copyright 1994-2024 Michael Slinn. All rights reserved.
If you would like to request to use this copyright-protected work in any manner,
please send an email.
This website was made using Jekyll and Mike Slinn’s Jekyll Plugins.