Подтвердить что ты не робот

Scala Опция [Future [T]] to Future [Option [T]]

Как преобразовать Option[Future[T]] в Future[Option[T]] в scala?

Я хочу использовать его в:

val customerAddresses = for {
  a <- addressDAO.insert(ca.address) // Future[Address]
  ia <- ca.invoiceAddress.map(addressDAO.insert) // Option[Future[Address]]
} yield (a, ia) // Invalid value have to be two futures

Здесь метод вставки подписей

def insert(address: Address): Future[Address]

ca является CustomerData​​p >

case class CustomerData(address: Address, invoiceAddress: Option[Address])
4b9b3361

Ответ 1

import scala.concurrent.Future
import scala.concurrent.ExecutionContext

def f[A](x: Option[Future[A]])(implicit ec: ExecutionContext): Future[Option[A]] = 
  x match {
     case Some(f) => f.map(Some(_))
     case None    => Future.successful(None)
  }

Примеры:

scala> f[Int](Some(Future.successful(42)))
res3: scala.concurrent.Future[Option[Int]] = Success(Some(42))

scala> f[Int](None)
res4: scala.concurrent.Future[Option[Int]] = [email protected]

Ответ 2

Стандартная библиотека предоставляет методы для использования Future.sequence по опции, к сожалению, вам нужно их собрать.

Как быстрый метод:

def swap[M](x: Option[Future[M]]): Future[Option[M]] =
    Future.sequence(Option.option2Iterable(x)).map(_.headOption)

Примечание. Я обнаружил, что неявный Option.option2Iterable уже доступен для меня. Поэтому вам может не понадобиться его предоставлять, уменьшая код до Future.sequence(x).map(_.headOption)

Или вы можете предпочесть метод расширения:

implicit class OptionSwitch[A](f: Option[Future[A]]) {
    import scala.concurrent.Future

    def switch: Future[Option[A]] = Future.sequence(Option.option2Iterable(f))
      .map(_.headOption)
  }


val myOpt = Option(Future(3))
myOpt.switch

Ответ 3

Вот еще одно решение:

def swap[T](o: Option[Future[T]]): Future[Option[T]] =
  o.map(_.map(Some(_))).getOrElse(Future.successful(None))

Трюк состоит в том, чтобы преобразовать Option[Future[T]] в Option[Future[Option[T]]], что легко, а затем извлечь из этого значения Option.