fommil
fommil

Reputation: 5885

flatten the Option part of a Future[Option[Option[T]]]

I have a results: List[Future[Option[T]]] which contains (parallel) calculations.

I want to obtain the first non-None result as soon as possible, or return None if all the calculations return None.

Currently, I'm doing this (which I consider to be ugly) to handle the case where Future.find doesn't find any results.

Future.find(results)(r => r.isDefined) map { 
  case Some(hit) => hit
  case _ => None
}

which will give me a Future[Option[T]] (what I want).

Is there a cleaner way to obtain the Future[Option[T]]: i.e. without having to manually flatten Future[Option[Option[T]]]?

Upvotes: 3

Views: 909

Answers (1)

Ben James
Ben James

Reputation: 125217

Rather than specialise this to Options, you could write a general function such as:

def collectFirst[A, B](futures: List[Future[A]])(pfn: PartialFunction[A, B])
    (implicit ex: ExecutionContext): Future[Option[B]] =
  Future.find(futures)(pfn.isDefinedAt) map (_.collect(pfn))

In terms of this, you could rephrase your problem as:

collectFirst(results) { case Some(hit) => hit }

Upvotes: 1

Related Questions