Friday, October 19, 2007

Psst ... Erlang has mutable state

The first thing you learn when picking up Erlang is "What? you mean I can't change a variable?" Example? The following fails.
X = 1.
X = 2.
Error in process <0.73.0> on node 'a@byrned.thoughtworks.com' with exit value: {{badmatch,2},[{erl_eval,expr,3}]}
When runtime encounters the second line of code it tries to "unify" both sides of the equation. The error is thrown because X is already bound to 1. You can get around this whenever you really need to by telling Erlang to forget the binding. Whether or not you should is a separate matter.
X = 1.
f(X).
X = 2.
Erlang is often described as a language with "no side effects" and no mutable state. I don't mean to let the cat out of the bag, but, it DOES. Check out built in functions get() and put(). Each Erlang process has a map that can be accessed via get and put, behaving much like ThreadLocal.

(node@byrned.thoughtworks.com)16> put(foo, 8).
undefined
(node@byrned.thoughtworks.com)17> get(foo).
8
(node@byrned.thoughtworks.com)18> put(foo, 9).
8
(node@byrned.thoughtworks.com)19> get(foo).
9

Use these at your own discretion, but try to forget where you learned it from.

4 comments:

Sidu said...

I suspect you meant to say 'because X is already bound to 1' in the second paragraph...

David Welton said...

Or you can use the gen_server trick of having a recursive loop that 'stores' data in a process. Basically, it works like this:

* You spawn a process that can receive messages.

* When it receives a 'put' message, for example, it adds the value to its data, and does a tail call to itself, passing the new data along, and waiting again to receive a message.

* When you then do a get, it has the data available, and can send it. Then it does a tail call to itself...

* Etc...

That seems to be another popular way of doing state.

Not Dennis Byrne said...

Thanks Sidu, I have corrected it to "bound to 1".

Terry said...

Who ever told you that Erlang has no side effects, never actually paid attention to this topic. Functional Languages minimize side effects. They do no completely remove them. This is not Erlang specific but all FL's share this property