Future [Option [Future [Option [Boolean]] Simplify futures and options?

I tried to simplify the way to create futures in Scala. At some point I got it Future[Option[Future[Option[Boolean]], but I simplified it below. Is there a better way to simplify this?

Passing the future β€œfailed” does not seem like the best way to do this. those. in a consistent world, I just returned "FAIL !!" at any time when he failed, and did not continue to the end. Are there other ways?

val doSimpleWork = Future {
  //Do any arbitrary work (can be a different function)
  true //or false
}

val doComplexWork = Future {
  //Do any arbitrary work (can be a different function)
  Some("result") //or false
}

val failed = Future {
  //Do no work at all!!! Just return
  false
}

val fut1 = doSimpleWork
val fut2 = doSimpleWork

val fut3 = (fut1 zip fut2).map({
  case (true, true) => true
  case _ => false
})

val fut4 = fut3.flatMap({
  case true =>
    doComplexWork.flatMap({
      case Some("result") =>
        doSimpleWork
      case None =>
        failed
    })
  case false =>
    failed
})

fut4.map({
  case true =>
    "SUCCESS!!!"
  case _ =>
    "FAIL!!"
})
+5
source share
3 answers

, , Futures val, , (val x = Future {...}). , .

- , onFailure:

def one = future { println("one") ; Some(1) }
def two = future { println("two") ; throw new Exception("no!"); 2 }
def three = future { println("three") ; 3 }

val f = one flatMap {
  result1 => two flatMap {
    result2 => three
  }
}

f onFailure {
  case e: Exception =>
    println("failed somewhere in the chain")
}

, "" , two. :

one 
two 
failed somewhere in the chain
+3

a " " , "" , "Scala" . , Monad OptionT , , Option[Unit] (Some(()) == true None == false), :

import scalaz._
import Scalaz._
import scala.concurrent._
import ExecutionContext.Implicits.global
import scala.concurrent.duration._
object Foo {

  // We need a Monad instance for Future, here is a valid one, or you can use the implementation
  // in the scalaz-contrib project, see http://typelevel.org
  implicit def futureMonad(implicit executor: ExecutionContext): Monad[Future] = new Monad[Future]  {
    override def bind[A, B](fa: Future[A])(f: A β‡’ Future[B]) = fa flatMap f
    override def point[A](a: β‡’ A) = Future(a)
    override def map[A, B](fa: Future[A])(f: A β‡’ B) = fa map f
  }

  // OptionT allows you to combine the effects of the Future and Option monads
  // to more easily work with a Future[Option[A]]
  val doSimpleWork : OptionT[Future,Unit] = OptionT(Future {
    // Option[Unit] is isomorphic to Boolean
    Some(()) //or None
  })

  val simpleFail : OptionT[Future,Unit] = OptionT(Future {
    None
  })

  val doComplexWork: OptionT[Future,String] = OptionT(Future {
    Some("result") //or None
  })

  val f1 = doSimpleWork
  val f2 = doSimpleWork
  val f3 = doComplexWork
  val f4 = doSimpleWork

  def main(argv: Array[String]) {
    val result = for {
      _ <- f1
      // we don't get here unless both the future succeeded and the result was Some
      _ <- f2  
      _ <- f3
      r <- f4
    } yield(r)

    result.fold((_ => println("SUCCESS!!")),println("FAIL!!"))

    // "run" will get you to the Future inside the OptionT
    Await.result(result.run, 1 second)
  }
}
+3

- , :

  def doSimpleWork = Future{
    //do some simple work
    true
  }

  def doComplexWork = Future{
    //do something complex here
    Some("result")
  }

  val fut1 = doSimpleWork
  val fut2 = doSimpleWork

  val fut = for{
    f1Result <- fut1
    f2Result <- fut2
    if (f1Result && f2Result)
    f3Result <- doComplexWork
    if (f3Result.isDefined)
    f4Result <- doSimpleWork
  } yield "success"

  fut onComplete{
    case Success(value) => println("I succeeded")
    case Failure(ex) => println("I failed: " + ex.getMessage)
  }

"" "" , :

  fut.recover{case ex => "failed"} onSuccess{
    case value => println(value)
  }

, , . , Futures, async. doSimpleWork boolean success/fail. doComplexWork - ( ) [String], . doSimpleWork . for comp fut1 fut2 ( ), , . , , fut val NoSuchElementException, , comp for. , doComplexWork . , Some, doSimpleWork. , "success". fut val, Future[String].

From there, we use one of the async callback functions to check whether the entire sequence of calls went completely (case Success), or failed somewhere in the process (case Failure), printing something related to the case in which it got . In the alternative end block of code, we recover from any possible failure by returning String "failed", and then use only a callback onSuccessthat will print either "success" or "unsuccessful" depending on what happened.

+1
source

All Articles