我喜欢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。否?
答案 0 :(得分:11)
filter
对Future
没有意义,因为类型系统不知道要为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)
foreach
,map
,flatMap
,filter
等链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.filter或Try.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's和Alvaro Carrasco's答案中所示)。