[Note: This letter was originally written about Scala actors when Akka was still a separate framework. Nowadays (fall 2015), Akka have become the standard actor framework for Scala, as well as close to a de-facto standard for Java. Syntax looks different when defining an actor, but the basic idea still holds - there is no language magic, just a library of very clever code.]
Dear Junior
First time I tried out actors in Scala I though: "OK, there is a fair amount of magic going on here". I have later realised that there is actually no magic at all involved, but I would like to share with you my misconception and how it cleared out.
I am talking about syntax like
vlad ! Godot
and like
receive {
case Godot => ...
}
The good part is that once I had my misconceptions cleared out, it was much easier to understand some weird parts of the Scala standard actors, and the path to understanding the design of
Akka became much clearer.
What I Mean with Magic
Let me for a brief moment clarify what I mean with "magic" in this context. A program consists of two parts - those I can build myself, and those where magic occurs. And when there is magic, there are often some magic words involved.
Take for example the thread model of Java (and the JVM) where objects can be "locked". Down in the runtime, each object has a lock associated with it and this lock can be "obtained" using the magic formula
synchronized (objectToLock) { … }
Here “synchronized” is a special construct to handle those locks. There is no way for me to create a lock with the same functionality through "ordinary programming". I have to wave my wand and utter that precise magic phrase - then I conjure the object-locks down in the runtime to do my bidding.
In language design these constructions are sometimes referred to as "special forms" because they often have special syntax.
Another example of special forms is the for construct in Scala
for(vlad <- vladimirs) { vlad.start() }
There is no way for me as a programmer to build a construct that behaves the same way. The special syntax is built into the language, and reserved for some special behaviour decided by the language designers. For me as a programmer – some magic occurs. I can understand its effect, but not reproduce how it works.
The actor syntax in Scala definitely looked like this kind of magic to me.
The Stage
Let me start with what confused me. To simplify the discussion slightly, there are two places where there seem to be "magic" involved about actors: on the outside, and on the inside.
Allow me to reuse
my example of the actor "Vladimir" with inspiration from Waiting for Godot.
On the "outside" of the actors we have the way one actor sends a message to another actor. A really simplified example is a script that creates an actor and then sends a message to it.
object vladimirwaitandrun extends Application {
val vlad = new Vladimir(42)
vlad.start()
vlad ! Godot
}
In this example we assume that the class "Vladimir" is defined as an actors, and that "Godot" is a simple message type (defined as a case class). Now what looks very "magic" to me is the line where the message is sent.
vlad ! Godot
This does not look like ordinary Scala syntax to me. It looks like one of those special forms with its associated magic going on.
We will later see that I was mistaken here.
On the "inside" we have how the actor reacts on messages that are passed to it. In Scala standard actors this happens inside the "act" method of a class that extends "actors.Actor"
class Vladimir (id : Int) extends actors.Actor {
def name: String = {
"Vladimir" + id
}
def act() = {
println(name + " is waiting ")
receive {
case Godot =>
println(name + " saw Godot arrive! ")
}
println(name + "'s wait is over ")
}
}
In this code the "receive-block" matches out arrived messages and run the appropriate code for the message.
receive {
case Godot =>
println(name + " saw Godot arrive! ")
}
Well, this is the thread-based model, there is also the event-based model where "receive" is replaced with "react" and does something very similar. The difference is beside the point for this discussion, but this discussion is crucial to understand the difference and its subtleties.
To me, this receive-block looks like a "special form" that invokes some magic. If anything, it reminds me of the synchronized-block mentioned earlier.
We will later see that I was mistaken here as well.
To make the setting of the stage complete, let us run the script that creates an actor and sends a message to it, a message upon which the actor reacts.
danbj$ scala godot.vladimirwaitandrun
Vladimir42 is waiting
Vladimir42 saw Godot arrive!
Vladimir42's wait is over
My Erlang Heritage
One way to explain my misconception is of course my preconceived notion based on my previous experience. When I first learned actor programming some fifteen years ago, I did so using Erlang.
In Erlang actors are called "processes" and they interact by dropping messages to each other. The receiving process reacts on the message and does something, very often to send other messages to other processes. The syntax for this message passing and handling is very tightly woven into the heart of the language.
The
syntax for dropping a message to another process looks like
NetlistenProcess ! terminateSignal
and the
syntax for receiving and reacting upon an incoming message looks like
receive
onhook ->
disconnect(),
idle();
end
Looks familiar, does it not?
Now, in Erlang both the exclamation mark (!) and "receive" are special forms in the language - syntax with a special meaning that unleashes some magic going on deep down in the runtime.
Seems not to far-fetched to assume same thing was going on in Scala.
However, I was mistaken. In Scala actors are just plain old objects with perfectly normal method calls. It is not even special syntax involved.
No Magic on the Outside
Now let us pick apart the "special syntax" for passing messages to see that there is actually no magic at all involved. We take a fresh look at the message-passing script.
object vladimirwaitandrun extends Application {
val vlad = new Vladimir(42)
vlad.start()
vlad ! Godot
}
We start with noting that Vladimir is in fact an object. It is an object that is instantiated from the class Vladimir and that object is referred to with the reference "vlad".
val vlad = new Vladimir(42)
Nothing magic here really.
What makes "vlad" an actor is that the class Vladimir is a subclass of Scala actors.Actor.
class Vladimir(id : Int) extends actors.Actor {
This means that all the methods that are defined in actors.Actor are inherited to Vladimir, and thus are available to call using the reference "vlad". And one of those methods are named "!" (pronounced “bang”).
As you are as curious as I am, we can even have a look at the definition of that method. We find it in ReplyReactor which is a trait that Actor makes use of.
override def !(msg: Any) {
send(msg, …)
}
So, “bang” is just a method, which we call on the actor to receive the message. We now realise that the strange syntax is just one way to write an ordinary method call.
vlad ! Godot
To make it totally obvious that this is just a method call, we can use the alternative syntax – the one that looks a little bit more familiar to people used to the syntax of C++/Java/C#.
vlad.!(Godot)
Oh, yes, that means exactly the same thing. It compiles and runs the same way.
danbj$ scala godot.vladimirwaitandrun
Vladimir42 is waiting
Vladimir42 saw Godot arrive!
Vladimir42's wait is over
Now, I do agree that the exclamation mark feels like a weird method name. Now, remember that in ReplyReactor everything method “bang” did was to delegate to method “send”.
override def !(msg: Any) {
send(msg, …)
}
To make things more “object-readable” we can inline the body of “bang” and use “send” instead. Only difference is that “send” takes another argument, but for the purpose of this discussion that does not make any difference – we can send in null there in this case.
The “send” method in its turn is just an ordinary method. It takes the argument (the message) and stuffs it into the mailbox – which is just some kind of list. There the message will sit waiting for processing, but that is not anything that concerns the “send” method. In other words – it is a very ordinary method.
There is no need to dig into details, but there is no magic going on. Now we can change the script to use the alternative syntax and "send" as method.
object vladimirwaitandrun extends Application {
val vlad = new Vladimir(42)
vlad.start()
vlad.send(Godot, null);
}
Now, this looks like plain use of an object, does it not? No magic, just a method call.
No Magic on the Inside Either
Now, on the inside of the actor we have the magic "act" method, which contains
receive {
case Godot =>
println(name + " saw Godot arrive! " + threadid)
}
Now, surely this must be some "special form" syntax with associated magic?
To start with, there is nothing magic with the method "act". It is just a choice of name for the code where the actor has its code for "this is what you do". In a way, it is just like the "run" method in the Java interface "Runnable" - just a way to point out what code to run in a separate thread when the actor is started.
When it comes to the recieve-block it turns out to be no magic there either. In fact, "receive" is just a utility-method in the framework class "actors.Actor". Remember that we created the actor by letting the class Vladimir subclass "actors.Actor".
class Vladimir(id : Int) extends actors.Actor {
Thus our class Vladimir contains all the methods that are in Actor. And one of those methods is "receive". In the code-block it looks like "receive" is a keyword, but it is just a call to the method "receive" defined in the super-class. We can make this a little bit clearer by writing that explicitly.
this.receive {
case Godot =>
println(name + " saw Godot arrive! ")
}
Now the code-block with the case clause seems to be hanging into thin air. But it does not. According to the syntax of Scala it is the argument for the method. We can make that clearer by putting the argument inside parentheses.
this.receive ({
case Godot =>
println(name + " saw Godot arrive! ")
})
Still looks a little bit weird?
Well, remember that in Scala a function (like "sqr") is also a value. And, as such, it can be passed as an argument to a method (like the list-method "map" for example). Now, the code-block we see is just a function defined "in-line". We can make things a little bit less convoluted by giving that function a name through a "val"-declaration.
val messagehandler: PartialFunction[Any, Unit] = {
case Godot =>
println(name + " saw Godot arrive! ")
}
this.receive (messagehandler)
I agree that the type of “messagehandler” becomes pretty weird – those partial functions are not always trivial to wrap your head around. But the important point is that the “messagehandler” is just a Scala value.
Let us revise the last line to have a look at what has happened to the “receive-block” that looked like a special form.
this.receive (messagehandler)
Viewed this way we see that "recieve" is just a method of the actor class. That method scans the mailbox for messages and does something when it finds a match. Now, to do this, the receive method must be told what to match and what to do about matches - an that is exactly what the (partial) method "messagehandler" does.
So the “special form” suspect seems to be just an ordinary method call. Just to ensure there is no magic, let us sketch if we could implement it ourselves.
Looping through the mailbox (a list) and searching for matches does not sound to complicated. Basically we just try to apply the message-handler and let it do its job. Of course there might be tricky corners, but there does not need to be any magic involved.
The only remaining magic is what "receive" does when there is no match. In that case it waits until there arrives a message, and then it tries to match the message-handler onto the newly arrived message.
Well, we can build even that part ourselves. If the mailbox is empty (or there are no matches) we can suspend the thread in a wait-state where we poll the mailbox at regular intervals. Even better, we can use the "notify" mechanism in the JVM where "receive" can call "mailbox.wait()" using the Java API. To wake up the thread we can let "send" (i e method "!") contain a "mailbox.notify()" so that the actor will resume its thread and rescan the mailbox.
And, basically, this is what the "thread-based actors" do. It is just someone else that has written the code for us.
No Magic at All
The syntax for sending messages ("!") and for receiving and reacting upon them "recieve {…}" looked like a lot of magic. However, it turned out that they where just ordinary methods defined on an ordinary class - the class "actors.Actor".
This is what is meant when people say that "Scala actors is not a language feature, it is a library". In other words: Scala actors are just ordinary code. The only thing that is special with that code is that it is pre-packaged together with the Scala download. However, it has no special status over any code written by you and me.
This design is actually very lucky for Scala. It has opened up for alternative actor frameworks to be written. The most prominent is Akka (champed by Jonas Bonér), and it has become so successful that the plan is to replace the standard actor library with Akka instead.
Of course, Akka is not magical either. It is just code which is very well designed and written. But in principle it is not different from code that could have been written by you and me. No magic involved.
Yours
Dan
ps Even if the Scala actors are not magic they are pretty cool anyway; cool enough to
understand the execution models.