Friday, March 20, 2009

Cloning Scala actors

I thought I'd base one of my projects on Scala actors. On the other hand seeing how actors are dynamically typed reminded me of my experiments with dynamic, clone based languages (Io, Ioke, Self, JavaScript).
The preferred way to create an actor in Scala is something like this:

val anActor = actor {
// here goes the body of an actor.: a loop, call to receive/react, message patterns...

The problem is I want to have a function cloneActor() that would return a clone of a scala actor:

val anotherActor = cloneActor(anActor)

Note that (for now) I don't want this actor's state to be cloned, just the body.
Just like if you would clone a human being: genetically identical body, but a fresh, clear memory...
At first I thought about using reflection in order to create new instance of the existing actor.

val reflectivelyClonedActor = anActor.getClass.newInstance // this won't work

Even if it didn't throw a run-time exception it wouldn't clone the body of the actor. :-(
The body is a closure passed to the method.
Second idea was to just create a new actor in a standard way, but reflectively copy the body... Unfortunately the body isn't kept in a explicitly declared field.
Althought there is a implicitly created synthetic field body$1, it's marked private final by the compiler.

scala> a1.getClass.getDeclaredField("body$1").get(a1)
java.lang.IllegalAccessException: Class can not access a member of class scala.actors.Actor$$anon$1 with modifiers "private final"
at sun.reflect.Reflection.ensureMemberAccess(
at .....

Well it was too tricky in the first place... OK. Out of ideas. Let's look at the source of

def actor(body: => Unit): Actor = {
val actor = new Actor {
def act() = body

Interesting thing is that act() has type () => Unit while body has type => Unit.
So we can freely use existing actor's act as a body of new actor. Voila!

def cloneActor(a: Actor) = actor(a.act)

Sure it has it's downsides...
What's more interesting if you want to treat actor as wrappers for threads to use all 8 cores of your shiny new machine:

implicit def intmulact(i: Int) = new {
def *(a: scala.actors.Actor) = (1 to i) map { _ => cloneActor(a) } toList

val executors = 8 * actor {
// body of the actor


  1. just an as an FYI, (i like your final solution better) you can get around private in reflection using setAccessible = true

  2. Thanks... I haven't programmed much Java before learning Scala... :-)