将`Future [Option [X]]`转换为`Option [Future [X]]`

时间:2013-10-18 12:54:59

标签: scala

如何将Future[Option[X]]转换为Option[Future[X]]

val futOpt:Future[Option[Int]] = future(Some(1))
val optFut:Option[Future[Int]] = ?

更新

这是this question的后续行动。我想我正试图抓住优雅地改造嵌套的未来。我正试图通过Option来实现Seq uces可以做什么,您可以将Future[Seq[Future[Seq[X]]]]转换为Future[Future[Seq[Seq[x]]]],然后转换为flatMap双层。正如Ionut澄清的那样,我按照翻转的顺序表达了这个问题,它应该是Option[Future[X]] - > Future[Option[X]]

2 个答案:

答案 0 :(得分:31)

不幸的是,如果不丢失计算的非阻塞属性,这是不可能的。如果你想一想就很简单。在None完成之前,您不知道计算结果是Some还是Future,因此您必须Await。那时,再拥有Future是没有意义的。您只需返回Option[X],因为Future已经完成。

看看这里。它总是返回Future.successful,它不进行任何计算,只是将o包裹在Future中,没有充分的理由。

def transform[A](f: Future[Option[A]]): Option[Future[A]] =
  Await.result(f, 2.seconds).map(o => Future.successful(o))

所以,如果在你的上下文中有意义阻止,你最好使用它:

def transform[A](f: Future[Option[A]]): Option[A] =
  Await.result(f, 2.seconds)

评论回复:

def transform[A](o: Option[Future[A]]): Future[Option[A]] =
  o.map(f => f.map(Option(_))).getOrElse(Future.successful(None))

答案 1 :(得分:0)

从技术上讲你可以做到这一点,唯一的条件是你有一个支持空的类型的类型类(例如 Monoid)


  def fut2Opt[A: Monoid](futOpt: Future[Option[A]])(implicit ec: ExecutionContext): Option[Future[A]] =
    Try(futOpt.flatMap {
      case Some(a) => Future.successful(a)
      case None    => Future.fromTry(Try(Monoid[A].empty))
    }).toOption