To codify what other's have said, the first major improvement would be to let eta-expansion work for you instead of manually making closures:
def qux(x: Int): String = {
val s1 = foo(x).fold("defaultFoo")(f)
bar(s1).fold("defaultBar")(g)
}
You could also use a for...yield
comprehension to defer your default case until the end:
def qux(x: Int): String = {
val result = for { s1 <- foo(x); s2 <- bar(f(s1)) } yield { g(s2) }
result.getOrElse("default result")
}
The issue here is that you lose the error handling you have in the middle of your control flow, because the simpler combinators pass through None
cases. If you need to preserve that same flow, you might try this:
def qux(x: Int): String = {
val s1 = foo(x).map(f).getOrElse("defaultFoo")
bar(s1).map(g).getOrElse("defaultBar")
}
It's not hugely simpler than your original code, but it's a little terser, and pushes error handling to the end of each line. Or just leave out the intermediate variable, and make it a one-liner:
def qux(x: Int): String = bar(foo(x).map(f).getOrElse("defaultFoo")).map(g).getOrElse("defaultBar")