In the example below I get the exception java.util.NoSuchElementException: Future.filter predicate is not satisfied
I want to have the result Future( Test2 )
when the check if( i == 2 )
fails. How do I handle filter/if within a for comprehension that deals with composing futures?
Below is a simplified example that works in the Scala REPL.
Code:
import scala.concurrent.Future
import scala.util.{ Try, Success, Failure }
import scala.concurrent.ExecutionContext.Implicits.global
val f1 = Future( 1 )
val f2 = for {
i <- f1
if( i == 2 )
} yield "Test1"
f2.recover{ case _ => "Test2" }
f2.value
In your
for-comprehension
, you are filtering byi == 2
. Because the value off1
is not two, it will not yield aSuccess
but instead aFailure
. The predicate of the filter is not satisfied, as your errror message tells you. However,f2.recover
returns a newFuture
. The value off2
is not manipulated. It still stores theFailure
. That is the reason you get the error message when you callf2.value
.The only alternative I can think of would be using an
else
in yourfor-comprehension
as shown here.This will return
Some(Success(Test2))
as yourf3.value
does.I liked @pkinsky 's idea, and made a bit of improvement. I dropped code to create
Exception
object like this:shouldTrue
function is implemented using lihaoyi`s sourcecode library:Then it automatically generates more meaningful exception message:
Of course I figured out one solution myself. Perhaps there are better, more idiomatic, solutions?
This is a more idiomatic solution, in my opinion. This predicate function creates either a
Future[Unit]
or a failed future containing your exception. For your example, this would result in either aSuccess("Test1")
or aFailure(Exception("Test2"))
. This is slightly different from "Test1" and "Test2", but I find this syntax to be more useful.You use it like this: