I want to do something like this.
def foo(s : String): Future[Boolean] = Future {
val a = someLongRunningMethod
if(!a)
return false or throw some exception // what should i return
//do some more thing
val b= someMoreLongRunningMethod
if(b)
return true
return false
}
but not able to use return with boolean. I got type mismatch error.
Error:(32, 12) type mismatch;
found : Boolean(false)
required: scala.concurrent.Future[Boolean]
return false
I am new to Scala. I am using foo method as this. I am not sure if it's the best way to use it. Please suggest how should i achieve it ?
val r = foo("Nishant")
r.onComplete {
case Success(result) => {
//Do something with my list
println("success: " + result)
}
case Failure(exception) => {
//Do something with my error
println("failure")
}
}
val re = Await.result(r, 10 second)
In Scala last expression in the block is the return value of the codeblock or function. Keyword return is optional in scala.
Notice that we run second task only if one task returns true. If first task returns false then we are done. That means first task is really important for our computation as its the decision maker.
Your version modified:
def longRunning1: Boolean = ???
def longRunning2: Boolean = ???
import scala.concurrent.ExecutionContext.Implicits.global
def foo(s : String): Future[Boolean] = Future {
val a: Boolean = longRunning1
if(a) {
val b: Boolean = longRunning2
b
} else false
}
Version 1:
Run futures (computations or long running methods) simultaneously and choose the results later. Here we discard the result of the second computation if we consider or want the result of the first computation.
import scala.concurrent.ExecutionContext.Implicits.global
def foo(s: String): Future[Boolean] = {
val f1 = Future {
Thread.sleep(20000) //Just to simulate long running task
Random.nextBoolean()
}
val f2 = Future {
Thread.sleep(1000) //Just to simulate long running task
Random.nextBoolean()
}
(f1 zip f2) map {
case (false, _) => false
case (true, f2Result) => f2Result
case _ => false
}
}
Version 2:
Run first method and then based on the result of the first method try to run the second method one after other. Computation is chained using map.
import scala.concurrent.ExecutionContext.Implicits.global
def foo(s: String): Future[Boolean] = {
val f1 = Future {
Thread.sleep(20000) //Just to simulate long running task
Random.nextBoolean()
}
f1.map { result =>
if (result) result
else {
Thread.sleep(1000) //Just to simulate long running task
Random.nextBoolean()
}
}
}
I am trying to find a cleaner way to express code that looks similar to this:
def method1: Try[Option[String]] = ???
def method2: Try[Option[String]] = ???
def method3: Try[Option[String]] = ???
method1 match
{
case f: Failure[Option[String]] => f
case Success(None) =>
method2 match
{
case f:Failure[Option[String]] => f
case Success(None) =>
{
method3
}
case s: Success[Option[String]] => s
}
case s: Success[Option[String]] => s
}
As you can see, this tries each method in sequence and if one fails then execution stops and the base match resolves to that failure. If method1 or method2 succeeds but contains None then the next method in the sequence is tried. If execution gets to method3 its results are always returned regardless of Success or Failure. This works fine in code but I find it difficult to follow whats happening.
I would love to use a for comprehension
for
{
attempt1 <- method1
attempt2 <- method2
attempt3 <- method3
}
yield
{
List(attempt1, attempt2, attempt3).find(_.isDefined)
}
because its beautiful and what its doing is quite clear. However, if all methods succeed then they are all executed every time, regardless of whether an earlier method returns a usable answer. Unfortunately I can't have that.
Any suggestions would be appreciated.
scalaz can be of help here. You'll need scalaz-contrib which adds a monad instance for Try, then you can use OptionT which has nice combinators. Here is an example:
import scalaz.OptionT
import scalaz.contrib.std.utilTry._
import scala.util.Try
def method1: OptionT[Try, String] = OptionT(Try(Some("method1")))
def method2: OptionT[Try, String] = OptionT(Try(Some("method2")))
def method3: OptionT[Try, String] = { println("method 3 is never called") ; OptionT(Try(Some("method3"))) }
def method4: OptionT[Try, String] = OptionT(Try(None))
def method5: OptionT[Try, String] = OptionT(Try(throw new Exception("fail")))
println((method1 orElse method2 orElse method3).run) // Success(Some(method1))
println((method4 orElse method2 orElse method3).run) // Success(Some(method2))
println((method5 orElse method2 orElse method3).run) // Failure(java.lang.Exception: fail)
If you don't mind creating a function for each method, you can do the following:
(Try(None: Option[String]) /: Seq(method1 _, method2 _, method3 _)){ (l,r) =>
l match { case Success(None) => r(); case _ => l }
}
This is not at all idiomatic, but I would like to point out that there's a reasonably short imperative version also with a couple tiny methods:
def okay(tos: Try[Option[String]]) = tos.isFailure || tos.success.isDefined
val ans = {
var m = method1
if (okay(m)) m
else if ({m = method2; okay(m)}) m
method3
}
The foo method should do the same stuff as your code, I don't think it is possible to do it using the for comprehension
type tryOpt = Try[Option[String]]
def foo(m1: tryOpt, m2: tryOpt, m3: tryOpt) = m1 flatMap {
case x: Some[String] => Try(x)
case None => m2 flatMap {
case y: Some[String] => Try(y)
case None => m3
}
}
method1.flatMap(_.map(Success _).getOrElse(method2)).flatMap(_.map(Success _).getOrElse(method3))
How this works:
The first flatMap takes a Try[Option[String]], if it is a Failure it returns the Failure, if it is a Success it returns _.map(Success _).getOrElse(method2) on the option. If the option is Some then it returns the a Success of the Some, if it is None it returns the result of method2, which could be Success[None], Success[Some[String]] or Failure.
The second map works similarly with the result it gets, which could be from method1 or method2.
Since getOrElse takes a by-name paramater method2 and method3 are only called if they need to be.
You could also use fold instead of map and getOrElse, although in my opinion that is less clear.
From this blog:
def riskyCodeInvoked(input: String): Int = ???
def anotherRiskyMethod(firstOutput: Int): String = ???
def yetAnotherRiskyMethod(secondOutput: String): Try[String] = ???
val result: Try[String] = Try(riskyCodeInvoked("Exception Expected in certain cases"))
.map(anotherRiskyMethod(_))
.flatMap(yetAnotherRiskyMethod(_))
result match {
case Success(res) => info("Operation Was successful")
case Failure(ex: ArithmeticException) => error("ArithmeticException occurred", ex)
case Failure(ex) => error("Some Exception occurred", ex)
}
BTW, IMO, Option is no need here?
Suppose I have several futures and need to wait until either any of them fails or all of them succeed.
For example: Let there are 3 futures: f1, f2, f3.
If f1 succeeds and f2 fails I do not wait for f3 (and return failure to the client).
If f2 fails while f1 and f3 are still running I do not wait for them (and return failure)
If f1 succeeds and then f2 succeeds I continue waiting for f3.
How would you implement it?
You could use a for-comprehension as follows instead:
val fut1 = Future{...}
val fut2 = Future{...}
val fut3 = Future{...}
val aggFut = for{
f1Result <- fut1
f2Result <- fut2
f3Result <- fut3
} yield (f1Result, f2Result, f3Result)
In this example, futures 1, 2 and 3 are kicked off in parallel. Then, in the for comprehension, we wait until the results 1 and then 2 and then 3 are available. If either 1 or 2 fails, we will not wait for 3 anymore. If all 3 succeed, then the aggFut val will hold a tuple with 3 slots, corresponding to the results of the 3 futures.
Now if you need the behavior where you want to stop waiting if say fut2 fails first, things get a little trickier. In the above example, you would have to wait for fut1 to complete before realizing fut2 failed. To solve that, you could try something like this:
val fut1 = Future{Thread.sleep(3000);1}
val fut2 = Promise.failed(new RuntimeException("boo")).future
val fut3 = Future{Thread.sleep(1000);3}
def processFutures(futures:Map[Int,Future[Int]], values:List[Any], prom:Promise[List[Any]]):Future[List[Any]] = {
val fut = if (futures.size == 1) futures.head._2
else Future.firstCompletedOf(futures.values)
fut onComplete{
case Success(value) if (futures.size == 1)=>
prom.success(value :: values)
case Success(value) =>
processFutures(futures - value, value :: values, prom)
case Failure(ex) => prom.failure(ex)
}
prom.future
}
val aggFut = processFutures(Map(1 -> fut1, 2 -> fut2, 3 -> fut3), List(), Promise[List[Any]]())
aggFut onComplete{
case value => println(value)
}
Now this works correctly, but the issue comes from knowing which Future to remove from the Map when one has been successfully completed. As long as you have some way to properly correlate a result with the Future that spawned that result, then something like this works. It just recursively keeps removing completed Futures from the Map and then calling Future.firstCompletedOf on the remaining Futures until there are none left, collecting the results along the way. It's not pretty, but if you really need the behavior you are talking about, then this, or something similar could work.
You can use a promise, and send to it either the first failure, or the final completed aggregated success:
def sequenceOrBailOut[A, M[_] <: TraversableOnce[_]](in: M[Future[A]] with TraversableOnce[Future[A]])(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], executor: ExecutionContext): Future[M[A]] = {
val p = Promise[M[A]]()
// the first Future to fail completes the promise
in.foreach(_.onFailure{case i => p.tryFailure(i)})
// if the whole sequence succeeds (i.e. no failures)
// then the promise is completed with the aggregated success
Future.sequence(in).foreach(p trySuccess _)
p.future
}
Then you can Await on that resulting Future if you want to block, or just map it into something else.
The difference with for comprehension is that here you get the error of the first to fail, whereas with for comprehension you get the first error in traversal order of the input collection (even if another one failed first). For example:
val f1 = Future { Thread.sleep(1000) ; 5 / 0 }
val f2 = Future { 5 }
val f3 = Future { None.get }
Future.sequence(List(f1,f2,f3)).onFailure{case i => println(i)}
// this waits one second, then prints "java.lang.ArithmeticException: / by zero"
// the first to fail in traversal order
And:
val f1 = Future { Thread.sleep(1000) ; 5 / 0 }
val f2 = Future { 5 }
val f3 = Future { None.get }
sequenceOrBailOut(List(f1,f2,f3)).onFailure{case i => println(i)}
// this immediately prints "java.util.NoSuchElementException: None.get"
// the 'actual' first to fail (usually...)
// and it returns early (it does not wait 1 sec)
Here is a solution without using actors.
import scala.util._
import scala.concurrent._
import java.util.concurrent.atomic.AtomicInteger
// Nondeterministic.
// If any failure, return it immediately, else return the final success.
def allSucceed[T](fs: Future[T]*): Future[T] = {
val remaining = new AtomicInteger(fs.length)
val p = promise[T]
fs foreach {
_ onComplete {
case s # Success(_) => {
if (remaining.decrementAndGet() == 0) {
// Arbitrarily return the final success
p tryComplete s
}
}
case f # Failure(_) => {
p tryComplete f
}
}
}
p.future
}
You can do this with futures alone. Here's one implementation. Note that it won't terminate execution early! In that case you need to do something more sophisticated (and probably implement the interruption yourself). But if you just don't want to keep waiting for something that isn't going to work, the key is to keep waiting for the first thing to finish, and stop when either nothing is left or you hit an exception:
import scala.annotation.tailrec
import scala.util.{Try, Success, Failure}
import scala.concurrent._
import scala.concurrent.duration.Duration
import ExecutionContext.Implicits.global
#tailrec def awaitSuccess[A](fs: Seq[Future[A]], done: Seq[A] = Seq()):
Either[Throwable, Seq[A]] = {
val first = Future.firstCompletedOf(fs)
Await.ready(first, Duration.Inf).value match {
case None => awaitSuccess(fs, done) // Shouldn't happen!
case Some(Failure(e)) => Left(e)
case Some(Success(_)) =>
val (complete, running) = fs.partition(_.isCompleted)
val answers = complete.flatMap(_.value)
answers.find(_.isFailure) match {
case Some(Failure(e)) => Left(e)
case _ =>
if (running.length > 0) awaitSuccess(running, answers.map(_.get) ++: done)
else Right( answers.map(_.get) ++: done )
}
}
}
Here's an example of it in action when everything works okay:
scala> awaitSuccess(Seq(Future{ println("Hi!") },
Future{ Thread.sleep(1000); println("Fancy meeting you here!") },
Future{ Thread.sleep(2000); println("Bye!") }
))
Hi!
Fancy meeting you here!
Bye!
res1: Either[Throwable,Seq[Unit]] = Right(List((), (), ()))
But when something goes wrong:
scala> awaitSuccess(Seq(Future{ println("Hi!") },
Future{ Thread.sleep(1000); throw new Exception("boo"); () },
Future{ Thread.sleep(2000); println("Bye!") }
))
Hi!
res2: Either[Throwable,Seq[Unit]] = Left(java.lang.Exception: boo)
scala> Bye!
For this purpose I would use an Akka actor. Unlike the for-comprehension, it fails as soon as any of the futures fail, so it's a bit more efficient in that sense.
class ResultCombiner(futs: Future[_]*) extends Actor {
var origSender: ActorRef = null
var futsRemaining: Set[Future[_]] = futs.toSet
override def receive = {
case () =>
origSender = sender
for(f <- futs)
f.onComplete(result => self ! if(result.isSuccess) f else false)
case false =>
origSender ! SomethingFailed
case f: Future[_] =>
futsRemaining -= f
if(futsRemaining.isEmpty) origSender ! EverythingSucceeded
}
}
sealed trait Result
case object SomethingFailed extends Result
case object EverythingSucceeded extends Result
Then, create the actor, send a message to it (so that it will know where to send its reply to) and wait for a reply.
val actor = actorSystem.actorOf(Props(new ResultCombiner(f1, f2, f3)))
try {
val f4: Future[Result] = actor ? ()
implicit val timeout = new Timeout(30 seconds) // or whatever
Await.result(f4, timeout.duration).asInstanceOf[Result] match {
case SomethingFailed => println("Oh noes!")
case EverythingSucceeded => println("It all worked!")
}
} finally {
// Avoid memory leaks: destroy the actor
actor ! PoisonPill
}
This question has been answered but I am posting my value class solution (value classes were added in 2.10) since there isn't one here. Please feel free to criticize.
implicit class Sugar_PimpMyFuture[T](val self: Future[T]) extends AnyVal {
def concurrently = ConcurrentFuture(self)
}
case class ConcurrentFuture[A](future: Future[A]) extends AnyVal {
def map[B](f: Future[A] => Future[B]) : ConcurrentFuture[B] = ConcurrentFuture(f(future))
def flatMap[B](f: Future[A] => ConcurrentFuture[B]) : ConcurrentFuture[B] = concurrentFutureFlatMap(this, f) // work around no nested class in value class
}
def concurrentFutureFlatMap[A,B](outer: ConcurrentFuture[A], f: Future[A] => ConcurrentFuture[B]) : ConcurrentFuture[B] = {
val p = Promise[B]()
val inner = f(outer.future)
inner.future onFailure { case t => p.tryFailure(t) }
outer.future onFailure { case t => p.tryFailure(t) }
inner.future onSuccess { case b => p.trySuccess(b) }
ConcurrentFuture(p.future)
}
ConcurrentFuture is a no overhead Future wrapper that changes the default Future map/flatMap from do-this-then-that to combine-all-and-fail-if-any-fail. Usage:
def func1 : Future[Int] = Future { println("f1!");throw new RuntimeException; 1 }
def func2 : Future[String] = Future { Thread.sleep(2000);println("f2!");"f2" }
def func3 : Future[Double] = Future { Thread.sleep(2000);println("f3!");42.0 }
val f : Future[(Int,String,Double)] = {
for {
f1 <- func1.concurrently
f2 <- func2.concurrently
f3 <- func3.concurrently
} yield for {
v1 <- f1
v2 <- f2
v3 <- f3
} yield (v1,v2,v3)
}.future
f.onFailure { case t => println("future failed $t") }
In the example above, f1,f2 and f3 will run concurrently and if any fail in any order the future of the tuple will fail immediately.
You might want to checkout Twitter's Future API. Notably the Future.collect method. It does exactly what you want: https://twitter.github.io/scala_school/finagle.html
The source code Future.scala is available here:
https://github.com/twitter/util/blob/master/util-core/src/main/scala/com/twitter/util/Future.scala
You can use this:
val l = List(1, 6, 8)
val f = l.map{
i => future {
println("future " +i)
Thread.sleep(i* 1000)
if (i == 12)
throw new Exception("6 is not legal.")
i
}
}
val f1 = Future.sequence(f)
f1 onSuccess{
case l => {
logInfo("onSuccess")
l.foreach(i => {
logInfo("h : " + i)
})
}
}
f1 onFailure{
case l => {
logInfo("onFailure")
}
The traverse method from Future object stops at first failure. I want a tolerant/forgiving version of this method which on occurrence of errors carries on with the rest of the sequence.
Currently we have added the following method to our utils:
def traverseFilteringErrors[A, B <: AnyRef]
(seq: Seq[A])
(f: A => Future[B]): Future[Seq[B]] = {
val sentinelValue = null.asInstanceOf[B]
val allResults = Future.traverse(seq) { x =>
f(x) recover { case _ => sentinelValue }
}
val successfulResults = allResults map { result =>
result.filterNot(_ == sentinelValue)
}
successfulResults
}
Is there a better way to do this?
A genuinely useful thing (generally speaking) would be to be able to promote the error of a future into a proper value. Or in other words, transform a Future[T] into a Future[Try[T]] (the succesful return value becomes a Success[T] while the failure case becomes a Failure[T]). Here is how we might implement it:
// Can also be done more concisely (but less efficiently) as:
// f.map(Success(_)).recover{ case t: Throwable => Failure( t ) }
// NOTE: you might also want to move this into an enrichment class
def mapValue[T]( f: Future[T] ): Future[Try[T]] = {
val prom = Promise[Try[T]]()
f onComplete prom.success
prom.future
}
Now, if you do the following:
Future.traverse(seq)( f andThen mapValue )
You'll obtain a succesful Future[Seq[Try[A]]], whose eventual value contains a Success instance for each successful future, and a Failure instance for each failed future.
If needed, you can then use collect on this seq to drop the Failure instances and keep only the sucessful values.
In other words, you can rewrite your helper method as follows:
def traverseFilteringErrors[A, B](seq: Seq[A])(f: A => Future[B]): Future[Seq[B]] = {
Future.traverse( seq )( f andThen mapValue ) map ( _ collect{ case Success( x ) => x } )
}
I'm new to scala and I try to combine several Futures in scala 2.10RC3. The Futures should be executed in sequential order. In the document Scala SIP14 the method andThen is defined in order to execute Futures in sequential order. I used this method to combine several Futures (see example below). My expectation was that it prints 6 but actually the result is 0. What am I doing wrong here? I have two questions:
First, why is the result 0. Second, how can I combine several Futures, so that the execution of the second Future does not start before the first Future has been finished.
val intList = List(1, 2, 3)
val sumOfIntFuture = intList.foldLeft(Future { 0 }) {
case (future, i) => future andThen {
case Success(result) => result + i
case Failure(e) => println(e)
}
}
sumOfIntFuture onSuccess { case x => println(x) }
andThen is for side-effects. It allows you to specify some actions to do after future is completed and before it used for something else.
Use map:
scala> List(1, 2, 3).foldLeft(Future { 0 }) {
| case (future, i) => future map { _ + i }
| } onSuccess { case x => println(x) }
6
I like this generic approach:
trait FutureImplicits {
class SeriallyPimp[T, V](futures: Seq[T]) {
def serially(f: T => Future[V])(implicit ec: ExecutionContext): Future[Seq[V]] = {
val buf = ListBuffer.empty[V]
buf.sizeHint(futures.size)
futures.foldLeft(Future.successful(buf)) { (previousFuture, next) =>
for {
previousResults <- previousFuture
nextResult <- f(next)
} yield previousResults += nextResult
}
}
}
implicit def toSeriallyPimp[T, V](xs: Seq[T]): SeriallyPimp[T, V] =
new SeriallyPimp(xs)
}
Then mix-in the above trait and use it like this:
val elems: Seq[Elem] = ???
val save: Elem => Future[Result] = ???
val f: Future[Seq[Result]] = elems serially save
This code could be improved to preserve the input collection type. See this article for example.