我该如何加入Option [Future [T]]?

时间:2015-12-01 02:00:42

标签: scala

我有以下代码

import scala.concurrent.{Future, Await}
import scala.concurrent.duration.Duration

import scala.concurrent.ExecutionContext.Implicits.global

def later(v: Int) = Future.successful(v)

val data = List(
  (1, Some(1), Some(2)),
  (2, Some(1), None),
  (3, None, Some(2)),
  (4, None, None)
)

def wait[T](v: Future[T]) = Await.result(v, Duration.Inf)


def seq[T](v: Option[Future[T]]): Future[Option[T]] = Future.sequence(v.toList).map(_.headOption)
def join[A, B](a: Option[Future[A]], b: Option[Future[B]]): Future[(Option[A], Option[B])] = seq(a).zip(seq(b))

wait(Future.sequence(data.map{ case (a, b, c) =>
  join(b.map(later), c.map(later)).map((a, _))
})) == List(
  (1, ((Some(1), Some(2)))),
  (2, ((Some(1), None))),
  (3, ((None, Some(2)))),
  (4, ((None, None)))
)

我想知道是否还有其他方式来编写join函数

2 个答案:

答案 0 :(得分:3)

如果您愿意使用Scalaz,则可以省略OptionList之间的转换,以便能够sequence这两个值。

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

import scalaz.std.option._
import scalaz.std.scalaFuture._
import scalaz.syntax.traverse._

def join[A, B](o1: Option[Future[A]], o2: Option[Future[B]]) =
  o1.sequence zip o2.sequence

答案 1 :(得分:0)

不使用其他辅助函数:

  def join[A, B](a: Option[Future[A]], b: Option[Future[B]]): Future[(Option[A], Option[B])] =
    (a, b) match {
      case (Some(fa), Some(fb)) =>
        for {
          vfa <- fa
          vfb <- fb
        } yield Some(vfa) -> Some(vfb)
      case (Some(fa), None) => fa map (Some(_) -> None)
      case (None, Some(fb)) => fb map (None -> Some(_))
      case _ => Future.successful(None -> None)
    }