Scala Try in Depth
A Try value is a container that holds either a success or a failure instead of throwing. In depth, Try means chaining risky steps while failures stay inside the value.
Try turns a risky parse into a safe value
Parsing 42 succeeds, and parsing abc fails. GetOrElse gives 0 for the failure.
@main def main(): Unit =
println(scala.util.Try("42".toInt).getOrElse(0))
println(scala.util.Try("abc".toInt).getOrElse(0))Map and recover handle success and failure
Tripling the parsed 10 gives 30. Recovering the bad parse with 0 gives 0.
@main def main(): Unit =
val tripled = scala.util.Try("10".toInt).map(_ * 3)
println(tripled.getOrElse(0))
val fixed = scala.util.Try("abc".toInt).recover { case _: NumberFormatException => 0 }
println(fixed.getOrElse(-1))FlatMap chains risky steps safely
100 divided by 20 is 5. Division by zero fails inside the Try, so the fallback is negative 1 and the Option form is None.
@main def main(): Unit =
val ok = scala.util.Try("20".toInt).flatMap(x => scala.util.Try(100 / x))
println(ok.getOrElse(-1))
val bad = scala.util.Try("0".toInt).flatMap(x => scala.util.Try(100 / x))
println(bad.getOrElse(-1))
println(bad.toOption)Example
@main def main(): Unit =
def parse(s: String): scala.util.Try[Int] = scala.util.Try(s.toInt)
val total = parse("12").flatMap(a => parse("8").map(b => a + b))
println(total.getOrElse(0))
val badTotal = parse("12").flatMap(a => parse("xx").map(b => a + b))
println(badTotal.getOrElse(0))
println(badTotal.toOption)Key points
- Success: the Try side that holds a computed value.
- Failure: the Try side that holds the failure instead of throwing it.
- GetOrElse on Try: unwraps a success or supplies a fallback for a failure.
- Map on Try: transforms a success and passes a failure through untouched.
- Recover on Try: replaces a matching failure with a fallback value.
In this example, parse wraps each text number in a Try. FlatMap adds 12 and 8 to give 20. When the second parse fails, the whole chain fails, so the fallback is 0 and the Option form is None.
Note
a Try never throws for the failure it captured. The failure is data that code can inspect.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Scastie
Exercise
What is scala.util.Try("7".toInt).map(_ * 2).getOrElse(0)?