如何最好地处理Future.filter谓词是不满意的类型错误

时间:2016-01-03 02:22:03

标签: scala playframework future

我喜欢scala的类型安全,但我一直遇到的一个运行时错误是

 Future.filter predicate is not satisfied

我可以看到为什么我收到此错误,只是寻找有关如何最好地解决此错误并优雅地处理它的建议,或者我做错了?

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

如果帐户未得到确认,我将收到上述错误。

我原以为,由于过滤器有可能失败,因此该scala会使yield返回值成为Option。否?

3 个答案:

答案 0 :(得分:11)

filterFuture没有意义,因为类型系统不知道要为else情况返回什么,因此依赖它是不安全的(通过使用一个if-guard)。但你可以在理解中做到这一点,以达到同样的目的:

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

(作为Jean Logeart的答案,但在理解中)

答案 1 :(得分:4)

您可能想要使用一个简单的flatMap,您可以在其中指定else案例:

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

答案 2 :(得分:-1)

foreachmapflatMapfilter等链for-comprehension is just syntax sugar。当你写if account.isConfirmed时,这个相当于使用Future的filter方法。

已解决的Future的值包含在Try中,可以采用Success或Failure的形式。 (将其与Option进行比较,可以采用Some或None的形式。)

如果包含的值在谓词中失败,Option&#39;} filter将Some转换为None,Future / Try filter方法会将Success转换为Failure。如果您查看Future.filterTry.filter的实施,可以通过返回包含您提到的new NoSuchElementException消息的predicate is not satisfied的失败来完成。

因此,错误消息本身完全是设计的,并且与类型系统一致。 for-comprehension中的任何步骤都只会生成另一个Future,因此如果if account.isConfirmed通过过滤器,则写if将成功成功,如果不通过则成为失败。

当您使用filter / <VisualBrush x:Key="vb_zoneOneAdvertisement" TileMode="None" Stretch="Uniform" AlignmentX="Center" AlignmentY="Center" > <VisualBrush.Visual> <MediaElement /> </VisualBrush.Visual> </VisualBrush> 时,这就是为什么Scala不会将Future [Result]更改为Future [Option [Result]]的答案。如果你想要一个成功的Future包含Option或一个空的Seq,你必须明确地这样做(如Jean Logeart'sAlvaro Carrasco's答案中所示)。