2
votes

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?

3
It would have been more interesting if you had researched your question just a tiny bit more.zxq9
Yes, it is a bit of an RTFM.rvirding
The question contains an error: in the Akka example the returned sum could be any of 0, 5, 6, 11 because while ordering is guaranteed, delivery is not.Roland Kuhn
In practice on a local machine it is roughly as reliable as a method call, but over a remote connection it depends on all aspects of the network between the two systems.Roland Kuhn
@RolandKuhn That is a pretty big issue to have to work around in code. Akka would be much more compelling were this not the case.zxq9

3 Answers

4
votes

the answer is yes, it is guaranteed: see the FAQ (it is not explicitly written, but the only way to send messages in a known order is to send them from the same process)

10.8  Is the order of message reception guaranteed?

Yes, but only within one process.

If there is a live process and you send it message A and then message B, it's guaranteed that if message B arrived, message A arrived before it.

On the other hand, imagine processes P, Q and R. P sends message A to Q, and then message B to R. There is no guarantee that A arrives before B. (Distributed Erlang would have a pretty tough time if this was required!)
4
votes

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.

0
votes

Yes, you can guarantee this case -- "Erlang messages" does not mean "simple UDP".

A can send B "1,2,3,4,5" and it will get exactly "1,2,3,4,5" in that order, regardless where A and B are in a cluster -- consider the implication of the last part of that statement....

What is not guaranteed is what order messages "a,b,c,d,e" from C to B will arrive at B relative to possible interleaving with A's concurrent message stream. "1,2,a,b,c,3,4,5,d,e" is as likely as "1,2,3,4,5,a,b,c,d,e" or any other interleaving of the two streams of independently ordered messages.