Last active
July 13, 2021 15:03
Try introduced in Scala 2.10.0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Start by adding these | |
import scala.util.{ Try, Success, Failure } | |
/** | |
* Sample runs code that raises the exception: | |
* java.lang.ArithmeticException: / by zero | |
*/ | |
object Sample { | |
def main(args: Array[String]): Unit = { | |
// Class Risky below is not guarding against division by zero, | |
// neither is the javaLike function so let's pass in | |
// a zero and see how they behave | |
val input = 0 | |
/* Output so you can see the results */ | |
println("javaLike [%d]" format javaLike(input)) | |
val risky = new Risky(input) | |
println("one [%s]" format risky.one) | |
println("two [%s]" format risky.two) | |
println("three [%d]" format risky.three) | |
println("four [%d]" format risky.four) | |
println("five [%s]" format risky.five) | |
println("six [%s]" format risky.six) | |
println("seven [%s]" format risky.seven) | |
println("eight [%s]" format risky.eight) | |
} | |
/** | |
* We can test what type `e` is, and trigger a variety of behaviors | |
* log info about the error context and return a default or raise | |
* the exception up the stack but really all I want is some elegant | |
* fault tolerance without each developer having to implement what | |
* that might look like all over an application | |
*/ | |
def javaLike(input: Int): Int = { | |
import util.control.NonFatal | |
try { | |
5 / input | |
} catch { | |
case _ ⇒ 5 / 5 | |
} | |
} | |
} | |
class Risky(input: Int) { | |
val num = 5 | |
/** Does not guard against blowing up. */ | |
def calculation: Int = num / input | |
/** Imagine this is an acceptable alternative */ | |
def fallback: Int = num / num | |
/** | |
* If the Try is successful returns a Some(value) | |
* else None. This is very clean and elegant. | |
*/ | |
def one: Option[Int] = Try(calculation).toOption | |
/** | |
* Useful for an expensive recursion, to test the | |
* status of something for example, before proceeding. | |
*/ | |
def two: Boolean = Try(calculation).isSuccess | |
/** | |
* Cleanly returns the successful outcome otherwise an alternative | |
*/ | |
def three: Int = Try(calculation) getOrElse fallback | |
/** | |
* Parses a Try where if successful returns the result, otherwise | |
* you can get into a variety of handling based on the type | |
* of Exception in the Failure. | |
*/ | |
def four: Int = Try(calculation) match { | |
case Success(v) ⇒ v | |
case Failure(_) ⇒ fallback | |
} | |
/* Now we get into the fun, integrating Try into function signatures. | |
These expose the Try for the caller to work with it directly. */ | |
/** | |
* The one will expose the exception naturally. | |
*/ | |
def five: Try[Int] = Try(calculation) | |
/** | |
* The one will not expose the exception if the fallback is successful. | |
*/ | |
def six: Try[Int] = Try(calculation) orElse Try(fallback) | |
/** | |
* Very much like the java try catch. Possibly useful | |
* for more complicated work where the recover case could | |
* raise an exception as well but why not just do the line | |
* above, it is more elegant. | |
*/ | |
def seven: Try[Int] = Try(calculation) recoverWith { | |
case _ ⇒ Try(fallback) | |
} | |
/** | |
* Similar to old school try catch clauses, and the above | |
* `recoverWith` but if you have to do this ask yourself first | |
* if you just have a design flaw and could do `orElse` instead. | |
*/ | |
def eight: Try[Int] = Try(calculation) recover { | |
case i: ArithmeticException ⇒ fallback | |
case e ⇒ throw e | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment