From the class Principles of Reactive Programming on Coursera:
"If an actor sends multiple messages to the same destination, they will not arrive out of order (this is Akka-specific)."
actors A and B
A sends B msg1 A sends B msg2
B will receive msg1 and then msg2
Warning: I've never programmed in Erlang
I believe that this message ordering semantic isn't guaranteed in Erlang. This seems like a HUGE difference that effects the different types of programs you could write using what are supposed to be similar frameworks.
For example in Akka you could do:
case class msg(x: Int)
case object report
class B extends Actor {
var i: Int = 0
def recieve = {
case msg(x) => i = i + x
case report => sender ! i
}
}
then you could do
A send B msg(5)
A send B msg(6)
A send B report // guarantees that the sum will be 11
My main point is in that Erlang it seems that you couldn't guarantee that the sum returned would be 11. Does Erlang discourage or even forbid Actors from containing any mutable state? Can anyone elaborate on the different type of programs that can and cannot be written with Actors in Scala's Akka vs. Erlang?
As Pascal said, the order of messages between two processes IS guaranteed. In Erlang, the only way to have some "mutable state" is to hide it behind actor. It is usually done this way:
loop(Sum) ->
NewSum = receive Message of
{msg, Number, Sender} -> add_and_reply(Sum, Number, Sender);
_ -> Sum
end,
loop(NewSum).
add_and_reply(Sum, Number, Sender) ->
NewSum = Sum + Number,
Sender ! NewSum,
NewSum.
This way, you don't mutate anything. You create new state and pass it as an argument in endless recursion. Actor that runs the loop makes sure, that all the calls are served one by one, because it accepts only one message at a time.
For me, the main difference between Erlang and Akka is preemptive scheduling. In Erlang, you can write actor that does this:
loop(Foo) ->
something_processor_consuming(),
loop(Foo).
and your system will work. Most of languages, where actors are added by library would go to this thread and it will be running forever blocking one CPU core from execution. Erlang is able to stop that thread, run something else and return back to it, so it plays nicely, even if you screw something up. Read more here. In Erlang, you can kill the process from outside exit(Pid, kill)
and it will terminate immediately. In Akka it will continue processing until it is ready for next message (you can simulate that with Erlang using trap_exit
flag).
Erlang was built with fault tolerance and soft real time systems in mind from the start, so OTP emphasises supervising processes. For example in Scala supervisor has the chance to resume child on error, while in Erlang child crashes on error and has to be restarted. This is because of assumption, that crash means bad state and we don't want propagate it.