Skip to content

Instantly share code, notes, and snippets.

@mielientiev
Last active March 20, 2017 11:28
Show Gist options
  • Save mielientiev/3d8237221df132bb125e3e04154f15fd to your computer and use it in GitHub Desktop.
Save mielientiev/3d8237221df132bb125e3e04154f15fd to your computer and use it in GitHub Desktop.
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success, Try}
object Main {
def main(args: Array[String]): Unit = {
val seq = Seq(Future("a"), Future("b"), Future(throw new NullPointerException("abc")), Future("c"))
val result: Future[(Seq[String], Seq[Throwable])] = convert(seq)
println(Await.result(result, Duration.Inf))
}
def convert(seq: Seq[Future[String]]): Future[(Seq[String], Seq[Throwable])] = {
seq.foldLeft(Future.successful((Seq.empty[String], Seq.empty[Throwable]))){
case (acc, element) => acc.flatMap{
case (results, errors) => element.transform{
case Success(str) => Try((results :+ str, errors))
case Failure(ex) => Try((results, errors :+ ex))
}
}
}
}
}
@mielientiev
Copy link
Author

mielientiev commented Mar 20, 2017

Scala 2.11

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}

object Main {

  def main(args: Array[String]): Unit = {

    val seq = Seq(Future("a"), Future("b"), Future(throw new NullPointerException("abc")), Future("c"))

    val result: Future[(Seq[String], Seq[Throwable])] = convert(seq)

    println(Await.result(result, Duration.Inf))
  }


  def convert(seq: Seq[Future[String]]): Future[(Seq[String], Seq[Throwable])] = {
    seq.foldLeft(Future.successful((Seq.empty[String], Seq.empty[Throwable]))) {
      case (acc, element) => acc.flatMap {
        case (results, errors) =>
          element.map(str => (results :+ str, errors)).recover {
            case ex: Throwable => (results, errors :+ ex)
          }
      }
    }
  }
}

@mielientiev
Copy link
Author

mielientiev commented Mar 20, 2017

Implementation with Future.sequence() & Either

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}

object Main {

  def main(args: Array[String]): Unit = {

    val seq = Seq(Future("a"), Future("b"), Future(throw new NullPointerException("abc")), Future("c"))

    val result: Future[(Seq[String], Seq[Throwable])] = convert(seq)

    println(Await.result(result, Duration.Inf))
  }


  def convert(seq: Seq[Future[String]]): Future[(Seq[String], Seq[Throwable])] = {
    val transformed: Seq[Future[Either[Throwable, String]]] = seq.map(f => f.map(str => Right(str)).recover{
      case err => Left(err)
    })
    Future.sequence(transformed).map(merge)
  }

  private def merge(seq: Seq[Either[Throwable, String]]): (Seq[String], Seq[Throwable]) = {
    seq.foldLeft((Seq.empty[String], Seq.empty[Throwable])){
      case ((results, errors), Left(ex)) => (results, errors :+ ex)
      case ((results, errors), Right(str)) => (results :+ str, errors)
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment