Saturday, 23 January 2010

Scala futures

I've been working with scala recently, and I've hugely enjoyed the experience.  It's changing the way I think about writing code, without having to bin the confidence I have about tuning and scaling the JVM in production.  Nor do I have to get my head round a completely new set of libraries.  Yup I still get the joy of using java.util.Date if I really want to (or, when my forehead gets tired of banging against that wall, I can stick with using org.joda.time.DateTime).

I am no doubt hopelessly old fashioned, but personally my brain works well with statically typed compiled languages.  When done well, it helps me get (non-trivial) stuff done faster.  This is definitely a suitable-for-how-my-mind-works preference: many people I hugely respect get on much better with dynamic languages.  Suck 'em all and see.  Scala is static typing done well: its type inference means it just happens most of the time and only occasionally do I need to be explicit.

I've enjoyed scala so much programming in Java now seems so "yuk".

A simple example of what I love about scala: futures done well.  Want to kick a long running activity off in another thread?  Here's how:

import scala.actors.Futures._

object App {
  def main(args: Array[String]) = {
    println("About to do something...")

    future {
      Thread.sleep(500)
      println("Slow thing finished")
    }

    println("I don't wait")
  }
}

// output is:
// About to do something...
// I don't wait
// Slow thing finished


This isn't a language feature of course: it's just part of the library.

Want to do a whole bunch of things in parallel and wait for them all?

package scala_actor

import scala.actors.Future
import scala.actors.Futures._

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

    var results = List[Future[Int]]()
    for (i <- 1 to 10) {
      println("Sending " + i + "...")
      val f = future {
        println("Processing " + i + "...")
        Thread.sleep(500)
        println("Processed " + i)
        i
      }
      println("Sent " + i)
      results = results ::: List(f)
    }

    results.foreach(future =>
      println("result: " + future()))
  }
}

//  output is: (on my machine)
//
//  Sending 1...
//  Processing 1...
//  Sent 1
//  Sending 2...
//  Processing 2...
//  Sent 2
//  Sending 3...
//  Processing 3...
//  Sent 3
//  Sending 4...
//  Processing 4...
//  Sent 4
//  Sending 5...
//  Processing 5...
//  Sent 5
//  Sending 6...
//  Processing 6...
//  Sent 6
//  Sending 7...
//  Processing 7...
//  Sent 7
//  Sending 8...
//  Processing 8...
//  Sent 8
//  Sending 9...
//  Processing 9...
//  Sent 9
//  Sending 10...
//  Processing 10...
//  Sent 10
//  Processed 1
//  result: 1
//  Processed 2
//  Processed 3
//  result: 2
//  result: 3
//  Processed 4
//  Processed 5
//  result: 4
//  Processed 6
//  result: 5
//  result: 6
//  Processed 7
//  Processed 8
//  result: 7
//  result: 8
//  Processed 9
//  Processed 10
//  result: 9
//  result: 10


I'm loving it.

3 comments:

Lookatbowen said...

What are you doing? Why are you using blog? Why not your own website?

Central Egg Command said...

Thanks for the simple example! I had heard about actors, but I was looking for some way to just have a thread do some work and return an answer. Do you know anything about whether futures are subject to lazy evaluation?

marcus.kazmierczak said...

Thanks for the great (and simple) example using futures in scala, I'm enjoying the language too