Future.filter 没有任何 if-guards 的运行时异常

Future.filter runtime exception without any if-guards

我偶尔会遇到 util.NoSuchElementException: Future.filter predicate is not satisfied 异常。

我从其他问题的理解是for comprehensions中出现if guards。我广泛使用 for comprehensions 但找不到任何条件。不过我确实做了一些作业。

for {
  foo <- Future{0}
  bar = foo + 1
} yield bar

不过,我的理解是这样应该没问题。

我正在努力寻找运行时异常的来源。除了 if guards 之外,还有其他情况会调用 Future.filter 吗?关于我应该寻找什么的任何其他想法?

编辑:

会不会是模式匹配导致的,比如

for {
  foo <- Future{0 -> 1}
  (bar, _) <- foo
} yield bar + 1

编辑2:

我猜上面的内容没问题,但这可能会导致 RTE?

for {
  (bar, _) <- Future{0 -> 1}
} yield bar + 1

.filter.withFilter(for-comprehension 首选的惰性版本)从 F[_] 中删除不满足谓词的值:

  • 对于 List,它从 List 中删除了值,returns 删除了这些值的 List
  • 如果未满足谓词
  • ,则使用 Option 将 Some 变为 None
  • with Try - 它与 Option 类似,但 Success 被视为 Some,而 Failure 被视为 None - 但是 Failure 不能为空,这就是为什么它将 Exception 放在那里
  • 未来是异步Try。

因此 .withFilter(condition) 基本上是

的懒惰版本
.flatMap { value =>
  if (condition(value)) => Future.successful(value)
  else Future.failed(new util.NoSuchElementException("Future.filter predicate is not satisfied"))
}

对于下面的 Future 调用 .withFilter 的每个案例,您都会得到它。对于理解将是:

  • 直接调用.withFilter
  • if 子句的用法
  • 模式匹配的使用
for {
  f <- future.withFilter(cond1) // this might raise exception
  g <- makeFuture(f) if cond2 // this might raise
  (head, tail) <- makeFutureList(g) // this might raise
} yield

避免它(在 Future 或其他 IO monad 中)

  • 不要手动调用 withFilter
  • 而不是 if 使用 if-else:
for {
  value <- future
  success <- if (cond(value)) Future.successful(value)
             else Future.failed(yourOwnError) // handle however you like
} yield success

你也可以使用更好的 monadic for 来避免在不能失败的模式匹配上使用 .withFilter(尽管如果他们失败了你仍然会得到异常,所以这不是一个解决方案,但仍然是一个很好的方式摆脱不需要的 .withFilter).