Reputation: 896
I am actually looking for a better Scala construct when it comes to return different results from Future on different conditions.
Lets say, inside a Future, I need to do certain validations before return a successful result. There are two ways to do so.
Way I:
Future {
if(!validation1()) return Future.failed("Validation1 failed!")
if(!validation2()) return Future.failed("Validation2 failed!")
if(!validation3()) return Future.failed("Validation3 failed!")
Future.successful()
}.flatMap(identity)
Way II:
Future {
if(!validation1())
Future.failed("Validation1 failed!")
else {
if(!validation2())
Future.failed("Validation2 failed!")
else {
if(!validation3())
Future.failed("Validation3 failed!")
else {
Future.successful("Results")
}
}
}
}.flatMap(identity)
But there is a problem with the Way I, it results in exception scala.runtime.NonLocalReturnControl. You can find the explaination in this link: https://tpolecat.github.io/2014/05/09/return.html
Which leaves us with Way II. The problem with this construct though is that it soon turns ugly with more number of validations.
Can anyone suggest a better way to express it?
Please let me know if this is the right place for this question or this question needs to be expressed in a better way.
TIA.
Upvotes: 4
Views: 204
Reputation: 923
What about:
def validation1(): (Boolean, String) // Tuple with e.g. (testResult, "Validation1 failed!")
def validation2(): (Boolean, String)
def validation3(): (Boolean, String)
val firstFound = Seq(validation1(), validation2(), validation3()).find(_._1)
if (firstFound.isEmpty) Success("Results") else Failure(firstFound.map{_._2}.get)
Upvotes: 0
Reputation: 4342
Consider to extract each validation into separate Future
def val1():Furure[String] =
if validation1() Future.failed("Validation1 failed") else Future.successful("Result")
def val2():Furure[String] =
if validation2() Future.failed("Validation2 failed") else Future.successful("Result")
def val3():Furure[String] =
if validation3() Future.failed("Validation3 failed") else Future.successful("Result")
and then chain them sequentially using flatMap
val1().flatMap(_ => val2()).flatMap(_ => val3())
or with syntactic sugar
for {
_ <- val1()
_ <- val2()
result <- val3()
} yield result
Upvotes: 4