Coming from an imperative programming background, one of the earliest things to note about Erlang is that variables don’t actually vary. Erlang allows you to assign a value to a variable once, and that’s it: the assignment is permanent. I like to think of it as going from the unknown to the known, or unbound to bound if you want to be precise.
1> X. * 1: variable 'X' is unbound
Which isn’t any different to Python:
>>> X Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'X' is not defined
In both cases X has an unknown value, it isn’t bound to anything, so Erlang/Python doesn’t know what to do with it.
Thus we need to assign a value to X:
2> X = 42. 42 3> X. 42
Now Erlang is happy, and so is Python:
>>> X = 42 >>> X 42
However, that = sign has a different meaning in the two languages. In Erlang, it’s not an assignment operator but a pattern matching operator. Erlang takes a look at both sides of the “equation” and attempts to make sense of it. Since X is unknown up to that point, the only way it can reconcile the statement is to assign X the value of 42. 42 equals 42, and the world is at one with itself again.
Python takes the value 42 and applies the label X to it. I could easily move the X label to something else:
>>> X = "foo" >>> X 'foo'
What I can’t do is the same with Erlang:
4> X = "foo". ** exception error: no match of right hand side value "foo"
Erlang, quite rightly, complains because it knows that X has the value 42 (since we bound it to that earlier) and this definitely doesn’t match the string “foo”. If I try it against the value 42, I get the value 42 i.e. a match.
5> X = 42. 42
In terms of naming, variables in Erlang must begin with a capital letter, not lowercase:
6> x = 7. ** exception error: no match of right hand side value 7
The reason this failed is that Erlang has something called an “atom”, and atoms start with lowercase letters. An atom is effectively a constant that has a value of itself: it’s pre-bound, so you can’t assign it to anything.
7> x. x
The atom x is equal to x, which is why Erlang raised an exception when x was compared to 7.
Why would you want variables that can’t change? Well, for those of you who have done any concurrent programming you will know how tricky it is dealing with shared data. Functional programming languages like Erlang remove a whole class of concurrency-related problems by making data immutable. If the data is immutable, you can’t have one thread or process changing the contents of a variable while another is looking at it. Nor can a process overwrite the changes another process has just made. That means no need for locks and semaphores to protect data integrity, all of which have performance implications.
Another thing it makes easier is debugging. Once a variable is set, it stays set – defective code can’t update a variable it shouldn’t. You can also more easily prove an algorithm, and its implementation, is correct when you know that code is free of side-effects.
If you’re a Pythonista looking at this and haven’t given Erlang a go, I can recommend it as a way to try something different and expand the mind. You might even gain a fresh perspective of the way you write Python. If you’re already an Erlang programmer, I hope my understanding of the above is correct and any feedback is always welcome!