Question

I have following Scala code, used with Scala 2.10

package reactive

import scala.concurrent.future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

object futuresum extends App {

  def f1 = future { 12 }
  def f2 = future { 13 }

  val result1 = f1.flatMap(x => f2.map(y => x + y))
  println(result1.value)

  val result2 = for (x <- f1; y <- f2) yield (x + y)
  println(result2.value)

}

This code should print 25, but it prints None:

None
None

What is wrong with this code?

EDIT

This works for me now:

package reactive

import scala.concurrent.future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.concurrent.Await
import scala.concurrent.duration.Duration

object futuresum extends App {

  def f1 = future { 12 }
  def f2 = future { 13 }

  val result1 = f1.flatMap(x => f2.map(y => x + y))
  result1.onComplete(b => println(b))

  val result2 = for (x <- f1; y <- f2) yield (x + y)
  result2.onComplete(b => println(b))

  Await.result(result1, Duration.Inf)
  Await.result(result2, Duration.Inf)
}
Was it helpful?

Solution 2

I'll steal Régis Jean-Gilles' excellent answer from https://stackoverflow.com/a/16358119/3328933

"Futures are executed on a dedicated thread pool. If your main program does not wait for the future, it will exit immediately and the future won't have a chance to execute. What you can do here is to use Await in your main program to block the main thread until the future executes:"

package reactive

import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.future
import scala.concurrent.duration._

object futuresum extends App {

    def f1 = future { 12 }
    def f2 = future { 13 }

    val result1 = f1.flatMap(x => f2.map(y => x + y))
    result1 onSuccess { case res => println(res) }
    Await.result(result1, 2 seconds)

    val result2 = for (x <- f1; y <- f2) yield (x + y)
    result2 onSuccess { case res => println(res) }
    Await.result(result2, 2 seconds)
}

OTHER TIPS

My guess is that between the "result"s and its println the futures haven't had enough time to spawn/send-to their threads. Check this quick REPL session:

scala> f1.flatMap(x => f2.map(y => x + y)).value
res2: Option[scala.util.Try[Int]] = None

scala> f1.flatMap(x => f2.map(y => x + y))
res3: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@1c9dac55

scala> res3.value
res4: Option[scala.util.Try[Int]] = Some(Success(25))

Let's try something different:

scala> f1.flatMap(x => f2.map(y => x + y)).onComplete(println(_))

scala> Success(25) // Press enter here. onComplete mixed with REPL output.

Another try:

scala> val later=f1.flatMap(x => f2.map(y => x + y)); later.onComplete(println(_)); println(later.value);
None
later: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@7019b737
Success(25)

Now that was a confusing output. It's a good illustration of my point, though:

  1. First, create later which contains a computation that will be executed sometime in future.
  2. Bind this computation with a event that will be triggered when it completes.
  3. Print the result of the possibly unfinished computation.

Now think in two lines of execution. 1, 2 and 3 happens in the first, main line of execution, or the main thread. What lies inside the future, { 12 }, map, flatMat happens in another line of execution.

Use Await.result(result, duration) or Thread.sleep to wait future thread finish. Then you can check future.isComplete to make sure that future is finished.

 Await.result(result2, 3 seconds)
 if(result2.isCompleted)
 println(result2.value)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top