Functional Programming with Erlang
Last week I was reading Joe’s new book Programming Erlang and just couldn’t seem to get my mind around Functional Programming. You see when Joe says
Concurrency is easy.
We don’t have shared memory. I have my memory, you have yours, we have two brains, one each, they are not joined together. To change your memory I send you a message, I talk or wave my arms. You listen, you see, your memory changes, but without asking you a question or observing your response I do not know that you have received my messages.
bHe’s completely correct. So, why is Erlang a functional language then? I ask this Because; if you have memory then you have state, and your state is modifiable. Each process should have an associated heap, or at least mutable declared statics. When I send you a message you should be able to update your private store of knowledge.
I know that what I’m talking about can be achieved in a functional program, that to implement this you’d use a variable in the functional call, which is passed via tail-recursion, and that this isn’t too inconvenient because we use tail-recursion anyway just to receive the next message. But if you’re an agent with a large accumulated dictionary of knowledge, making a new copy of that dictionary to send to yourself is rather wasteful of memory. Since it’s your knowledge you should be able to modify it in-place. Just like what we do in the real world.
So while Joe has the right idea about modeling things from the real-world using concurrency, I feel that he’s got the implementation wrong. But it just might be that my growing up on imperative languages has broken my mind.
You don’t make a copy of the data unless something changes, and then, you copy only what’s necessary. Since Erlang uses single-assignment semantics, the compiler knows that a data element, once allocated, cannot suddenly change. This means that it can safely pass a pointer to the data when e.g. calling a function.
A tuple, for example, is an array of pointers. When you modify a tuple, you create a new array of pointers, keeping the pointers to data that didn’t change. A large dictionary could be a tree of small tuples (pointer arrays). Updating the dictionary would then mean replacing the few small tuples leading down to the updated leaf.
This is the beauty of single-assignment semantics and automatic memory management. It can be made quite efficient, and it completely eliminates pointer errors.
Firstly, I’m really stoked that you decided to visit my humble page. Secondly, I’d like to apologize if I came off as ranting or ignorant.
In truth, I’m still learning the language. When I finally reached chapter 8, Concurrent Programming, I began to suspect that the interpreter was performing memory-sharing behind the scenes, and that I, as a programmer, was to think of it as message passing. This approach would seem to give Erlang an enormous performance advantage. As a programmer I get to reason about concurrency in a simpler, side-effect free, message passing world; while you guys implementing the language take care of all the gross and ugly optimizations that’re required on todays shared memory computers. To that I wish to thank you, and by extension the entire Erlang team. Your work really pays off.
If I were to implement a concurrent language, I would probably also make it a functional one. That way the language designer accepts the burden of optimization on behalf of the programmer, thereby freeing the programmer’s mind to think about their problem rather than their implementation details. It feels good that my inkling intuitions were correct, and that this was indeed the design chosen during Erlang’s implementation.
As a programmer I’d like to thank you for removing pointer errors. I always hated paying mental tax to that entire class of problems. It would be really awful to leave those things dangling around a concurrent program (gives me nightmares just thinking about it). I believe Erlang’s got really firm foundation and solid architecture; It’s just taking me time to get used to the syntax and new patterns of thought. (But my gut says the effort will pay off.)
My goodness you (eric) are verbose.
Erlang indeed does have a very good concept behind it. The more I learn the more I can see that every piece was considered and based on the founding ideas of the language.
I am pleased you are enjoying it as much as I have.