Erlang as an OO language

Created 9th August, 2007 03:58 (UTC), last edited 9th August, 2007 08:09 (UTC)

Lambda the Ultimate pick out some quotes from a blog post by Ralph Johnson.

The thing that bugs me about [Armstrong's] book (and about his talks) is that he make more fuss than he should about the functional language aspect of Erlang and not enough about the OO aspect. In fact, he denies that it is OO.

As I've been looking more and more at Erlang it strikes me more and more that there is an object oriented language hiding just below the surface. Ralph sums it up very well:

“sequential Erlang” is a functional programming language… “concurrent Erlang” is an object-oriented language.

Whenever I've thought about this I've thought that I must be mistaken given Joe Armstrong's dislike of object oriented systems (something I've written about before).

Daniel Lyons' response to my article was interesting, but not as interesting as some of the Erlang he sent me via email to illustrate his points¹ [1Normally I don't publish anything I get in private emails, so I hope Daniel doesn't mind.Update: I think he's OK about it because he's written a very useful follow up. Do read it.]. As an example he sent this code for a counter service:

-module(counter).
-export([start/0, stop/0, increment/0, decrement/0, current_count/0, counter_server/1]).

start() ->
    register(counter_server, spawn(?MODULE, counter_server, [0])).

stop() ->
    counter_server ! stop.

counter_server(Count) ->
    receive
        increment -> counter_server(Count+1);
        decrement -> counter_server(Count-1);
        {value, Pid} -> Pid ! {value, Count}, counter_server(Count);
        stop -> true
    end.

increment() -> counter_server ! increment.
decrement() -> counter_server ! decrement.
current_count() ->
    counter_server ! {value, self() },
    receive
        {value, Count} -> io:format("Received value: ~w~n", [Count]);
        _ -> io:format("error~n")
    end.

The counter itself is this bit:

counter_server(Count) ->
    receive
        increment -> counter_server(Count+1);
        decrement -> counter_server(Count-1);
        {value, Pid} -> Pid ! {value, Count}, counter_server(Count);
        stop -> true
    end.

In essence it is an object which receives one of three messages. Note that the implementation of the methods is in a functional style, but the counter_server itself is clearly an implementation of an object. But an implementation in a language which doesn't abstract out the object oriented message passing. This implementation of a message dispatcher-as-switch-statement is familiar to anybody who has written message pumps in GUI applications (notwithstanding that Erlang's “switch statements” are much smarter than those in most other languages).

Here is the same global counter service implemented in Mahlee (a concurrent message passing language extension to JavaScript):

function Counter( initial ) {
    this.value = ( initial || 0 );
    this.increment = function() {
        return ++this.value;
    }
    this.decrement = function() {
        return --this.value;
    }
    this.current = function() {
        return this.value;
    }
}

Here the message dispatching abstraction is built into the language so the switch statement is gone. It turns out that this isn't the only advantage though. Because the construction and object handling is also abstracted out at the language level we don't need to worry about any of this within the implementation of the counter. Most importantly, because object oriented languages also abstract out the message passing itself all of the explicit message sending that the Erlang version needs to do is also gone.

The counter is a bit longer, but much simpler to understand. Critically the implementation scales much better to more complex objects because we are using suitable abstractions to do the heavy lifting of the message dispatching and binding. Here is some code that uses the object:

function main() {
   var count_server = Mahlee.create( Counter );
   count_server.increment();
   count_server.decrement();
   FHost.echo( count_server.current().result() );
}

Note that the only difference between creating one of these objects to be accessible from all threads in Mahlee and only within one thread in Mahlee (a Mahlee object, or a normal JavaScript object respectively) is only in how the object is constructed. JavaScript already has message passing built into the syntax of the language so Mahlee is able to re-use that abstraction (it only re-routes the messages to the object in the remote thread) — although the future requires an extra call to pull out the resulting value.

I have to agree with Ralph, Erlang is an object oriented language, but one where the objects themselves are implemented in a functional language. Erlang is a lovely language, and the more I study it the more I think of it, but it makes Joe's attack on object orientation seem even more bizarre than I already thought it was.

I can only assume he was being ironic and I missed it.


Categories:

Discussion for this page