How best to handle the Future.filter predicate errors like

I like how scala is type safe, but one runtime error that I keep working with is

Future.filter predicate is not satisfied 

I see why I get this error, just looking for tips on how best to get around this error and handle it gracefully, or maybe I'm doing it wrong?

 val r: Future[play.api.mvc.Result] = for { account <- accountServer.get(...) if account.isConfirmed orders <- orderService.get(account, ...) } yield { ... } 

If the account is not verified, I will receive the above error.

I would think that since there is a chance that the filter will fail, scala will then make the return value an option. No?

+5
source share
3 answers

filter does not make sense for Future , because the type system does not know what to return for the else case, so it is unsafe to rely on it (using if-guard). But you can do this in understanding to achieve the same:

 val r: Future[play.api.mvc.Result] = for { account <- accountServer.get(...) orders <- if (account.isConfirmed) orderService.get(account, ...) else Future.successful(Seq.empty) } yield { ... } 

(as the answer of Jacques Logate, but within the limits of understanding)

+7
source

You probably want to use a simple flatMap in which you can specify the else case:

 val orders = accountServer.get(...) .flatMap { account => if(account.isConfirmed) orderService.get(account, ...) else Future.successful(Seq.empty) } 
+4
source

A for understanding is just syntactic sugar for the chain foreach , map , flatMap , filter , etc. When you write if account.isConfirmed , this is equivalent to using the Future filter method.

The meaning of the permitted Future is contained in Try, which can either take the form of Success or Failure. (Compare this with Option, which can take the form of Some or None.)

It appears that the Option filter converts Some to None, if the contained value does not give a predicate, the Future / Try filter methods convert success to failure. If you look at an implementation of Future.filter or Try.filter , this is done by returning a failure with a new NoSuchElementException containing the predicate is not satisfied that you mentioned.

Thus, the error message itself is entirely in design and corresponds to the type system. Any step in understanding will only project another Future, so the if account.isConfirmed entry will either project Success if it passes the filter or Fails if it is not.

This is the answer to why Scala will not change the Future [Result] into the Future [Variant [Result]] when you use if / filter . If you would like to have a successful Future containing Option or an empty Seq, you must do it explicitly (as shown in Jean Logeart and Alvaro Carrasco's Answers ).

-1
source

Source: https://habr.com/ru/post/1239703/


All Articles