First steps with `futures` in Scala

The recently released Scala 2.10.0 introduces futures and promises.

One of the most prominent highlights of this release, futures make it trivial to compose asynchronous multi-threaded apps.

And you can do so elegantly as I try to demonstrate with a few examples.

    // example 1
    //
    // `future` blocks asynchronously execute in a different thread and return a `val`
    // asynchronous results can be trapped via `onSuccess`, `onFailure` and `onComplete` callbacks

    val sayHello = future {
      Thread.sleep(1000)
      "hello"
    }

    sayHello onSuccess {
      case message => Console.println(s"He said '$message'")
    }

    Console.println("Waiting..")

    Thread.sleep(2000)

    // output
    //
    // Waiting..
    // He said 'hello'

    val tryDivideByZero = future {
      Thread.sleep(1000)
      1 / 0
    }

    tryDivideByZero onFailure {
      case e: ArithmeticException => Console.println(s"Don't be silly!")
    }

    Console.println("Try dividing by zero")

    Thread.sleep(2000)

    // output
    //
    // Try dividing by zero
    // Don't be silly!
  
    // example 2
    //
    // if one future depends on the result of another
    // you could nest callbacks
    // or use `map` to "chain" them
    // `map` returns a future which can be trapped via callbacks

    val firstLove = future {
      Thread.sleep(500)
      "i love you"
    }

    val thenBetray = firstLove map {
      case loveLetter => {
        Console.println(loveLetter)
        Thread.sleep(500)
        "not really"
      }
    }

    thenBetray onSuccess {
      case partingWords => Console.println(partingWords)
    }

    Thread.sleep(2000)

    // output
    //
    // i love you
    // not really
  
    // example 3
    //
    // multiple inter-dependent futures typically create a nested callback mess
    // this is avoided with the `for` construct
    // `for` can "chain" multiple futures, and "apply" another `future` on their results

    val calculateMyScore = future {
      Thread.sleep(500)
      new Random().nextInt(10)
    }

    val calculateYourScore = future {
      Thread.sleep(500)
      new Random().nextInt(10)
    }

    val doIWin = for {
      myScore <- calculateMyScore
      yourScore <- calculateYourScore
    } yield myScore > yourScore


    doIWin onSuccess {
      case b: Boolean => Console.println(if (b) "yes" else "no")
    }

    Console.println("Do I win?")

    Thread.sleep(2000)

    // output
    //
    // Do I win?
    // yes|no
  

The entire example - available on GitHub - is an executable application.

The main app runs on its own thread and each future block uses a thread from the global execution context thread pool.

Timers Thread.sleep(...) are included to simulate asynchronous calls.

Part 2: Controlling flow with Scala Futures