【问题标题】:Reducing two futures of options with _ orElse _ does not yield Some使用 _ orElse _ 减少期权的两个期货不会产生 Some
【发布时间】:2015-07-29 05:28:44
【问题描述】:

受到this question的启发,我认为以下是一个解决方案:

import scala.concurrent.Future

val x: Future[Option[Int]] = Future.successful { None }
val y: Future[Option[Int]] = Future.successful { Some(55) }

Future.reduce(Seq(x, y))(_ orElse _).value  // expecting Some(Success(Some(55)))

令我惊讶的是,在 REPL 中执行此操作大多会给出None,而会不规律地给出Some(55)

res80: Option[scala.util.Try[Option[Int]]] = None
res81: Option[scala.util.Try[Option[Int]]] = None
res82: Option[scala.util.Try[Option[Int]]] = None
res83: Option[scala.util.Try[Option[Int]]] = Some(Success(Some(55)))
res84: Option[scala.util.Try[Option[Int]]] = None

所以这对我来说是一个 Scala WTF 时刻。我错过了什么吗?

【问题讨论】:

    标签: scala future


    【解决方案1】:

    显然,两个期货都已完成并不重要,默认执行上下文可能仍会决定生成生成的未来,因此它可能只会在不久之后完成。

    Await.result(Future.reduce(Seq(x, y))(_ orElse _), Duration.Inf) // Some(55)
    

    【讨论】:

    • 确实如此。其他期货是否完成并不重要,因为减少本身可能需要一些时间,因此如果直接计算,操作将阻塞。因此,为了与 Future 相当激进的非阻塞 API 保持一致,它必须产生计算。
    【解决方案2】:

    这个较小的代码具有相同的结果:Future(42).value(有时打印None)。

    实际上问题在于您如何使用value 方法(来自scaladoc):

    如果未来未完成,则返回值为None

    如果你想确定它会产生一个价值,你需要等待未来。

    【讨论】:

      猜你喜欢
      • 2016-11-06
      • 1970-01-01
      • 2018-06-28
      • 1970-01-01
      • 1970-01-01
      • 2013-10-18
      • 1970-01-01
      • 2022-01-12
      • 2020-07-17
      相关资源
      最近更新 更多