I have several blocks of code that follow this pattern:
// Dummy function defs.
def result(i : Int, d : Double, b : Boolean) = {
if (b) d else i
}
def fA(s : String) = {7}
def fB(s : String, i : Int) = {1.0}
def fC(s : String, i : Int, d : Double) = {true}
// Actual code.
def test(s : String) : Double = {
try {
val a = fA(s)
try {
val b = fB(s, a)
try {
val c = fC(s, a, b)
result(a, b, c)
} catch {
case _ => result(a, b, false)
}
} catch {
case _ => result(a, 0.0, false)
}
} catch {
case _ => result(0, 0.0, false)
}
}
Where a, b, & c are calculated in turn by the corresponding functions and then the values are passed to the result function. If at any stage an exception occurs then a default value is used in place of the remaining variables.
Is there a more idiomatic way to express this code. It reminds me of Monads in that it’s a series of chained computations which bail out immediately if any computation fails.
These types of problems are just what
Tryaims to solve a bit more monadically (than nestedtry/catchblocks).Tryrepresents a computation that may either result in an exception, or return a successfully computed value. It has two subclasses for these–SuccessandFailure.Very funny that this question popped up when it did– a few days ago, I finished up some additions and refactoring to
scala.util.Try, for the 2.10 release and this SO question helps to illustrate an important use-case for a combinator that we eventually decided to include;transform.(As of writing this,
transformis currently in the nightly and will be in Scala from 2.10-M5 onward, due out today or tomorrow. More info aboutTryand usage examples can be found in the nightly docs)With
transform(by nesting them), this can be implemented usingTrys as follows: