Skip to content
laforge49 edited this page Jul 6, 2011 · 13 revisions

##What is an Actor?

An actor is a kind of object. The main difference between objects and actors is that you call functions on an object, but you pass messages to an actor. The advantage to doing this is that you separate control flow from data flow. For when you call a function on an object, the object "does its thing" and then returns some result. But when you pass a message to an actor, well, that's it. At some time, sooner or later, the actor will process the message and "do something" with the results. OK, we have a challenge here. Yow do you use actors and keep the code understandable?

Fortunately, in Scala it is relatively painless to write an anonymous callback.

someActor(somethingToDo) { result => println(result) }

We can even chain things together.

actor1(request) { result1 =>
  actor2(result1) { result2 => println(result2) }
}

##Processing a Message in an Actor

For every type of message that an actor receives, it has a function. And all the functions which an actor uses to process these messages have the same signature. So lets begin by defining some message classes and some functions to process them.

case class Times2(value: Int)
case class Add(value1: Int, value2: Int)

private def times2(msg: AnyRef, rf: Any => Unit) { rf(msg.asInstanceOf[Times2].value * 2) }
private def add(msg: AnyRef, rf: Any => Unit) {
  val req = msg.asInstanceOf[Add]
  rf(req.value1 + req.value2)
}

Functions which process the messages sent to an actor have two parameters. The first is the message; the second is a callback function used to pass back the results.

##Binding Functions to Message Classes

An actor needs to invoke the appropriate function for each message it receives. This is done using a table which is initialized with the bind function.

bind(classOf[Times2], times2)
bind(classOf[Add], add)

##A Simple Actor

Here then is the completed code.

class SimpleActor(mailbox: Mailbox) extends Actor(mailbox, null) {
  bind(classOf[Times2], times2)
  bind(classOf[Add], add)
  private def times2(msg: AnyRef, rf: Any => Unit) { rf(msg.asInstanceOf[Times2].value * 2) }
  private def add(msg: AnyRef, rf: Any => Unit) {
    val req = msg.asInstanceOf[Add]
    rf(req.value1 + req.value2)
  }
}

Clone this wiki locally