我有以下代码
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
函数
答案 0 :(得分:3)
如果您愿意使用Scalaz,则可以省略Option
和List
之间的转换,以便能够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)
}