A friend of mine has become an Erlang aficionado lately, and has - deliberately or not - pulled me into Erlang development
I had not touched Erlang in a long time but always knew there was something about it that bothered me some twelve years ago. I forgot what, but now remember.
This post is an attempt to clarify what bothered me - and still does to some extent - about this language. Before doing that, it is important to note that whataver deificiencies Erlang might have, it is - in my extremely humble opinion - currently one of three viable functional languages for big scale development, the other two being F# and Scala, relying on imperative execution environments (Java VM and .NET CLR..) Yes, there are Lisp implementations out there, but they are losing ground. Not like the good old Allegro Common Lisp days
As Philip Wadler and Simon Marlow put it, in a proposal to extend Erlang’s type system:
We can stop waiting for functional languages to be used in practice - that day is here!
Note: I am here focusing on the language, not the runtime execution environment, which is far ahead of any other functional programming language, or most languages for that matter. What other language provides light-weight processes with distributed message passing out of the box, while supporting hot swap of code? Did I forget to mention a transparently distributed database system (Mnesia)?
The Erlang approach is to bring academics into a pragmatic setting. Those are the two conceived worlds:
- the academic world of functional programming and pattern matching
- the pragmatic - dare I say “agile” world - of dynamically typed languages
The promise of Erlang is to be the best of both worlds. The Erlang developer should then be the prime example of The Pragmatic Academic.
I do not agree. I argue that Erlang is extremely clumpsy for problems involving a host of distinct notions, i.e., needing many different types, often intricately dependent on each other, ontologically or not.
The only compound types available to the Erlang developer are the tuples and lists. Just like with tables in Lua, you can emulate your own complex types via these Erlang tuples. That is the antipod to abstract data types, via the extremely extrovert representation, and is very hard to maintain for more complex types, especially since there is no type checking. With that “record”-based approach (no, I am not talking about the formal record that also exists Erlang…), it comes as no surprise that it is very susceptible to RDBMS, as shown by the eminent ErlyDB. Most developers take the approach of using the first element of the tuple as the “type”, or functor as it would be called in the Prolog days.
This lack of user-defined compound types has been observed by some Big Boys in the FP world, such as Marlow and Wadler.
But cannot dynamic typing be quite empowering? Yes, in one case and one case only: heterogeneous lists. In all other cases, the variable will have a “type” intended by the operations performed on it, and if those operations are hard to gather into “classes” or “types”, then one can use generic types in modern typed languages. I.e., just because you do not have to state a type does not mean that you do not have to have a specific “type” in mind when designing and coding. You do. If that mental “type” of yours is a set of possible operations, it is called a Concept in Generic Programming, and often implemented via templates or generics.
Ok, you save a few key strokes by not adorning the variable with a type, but so can type deduction do for you.
What about new types introduced in runtime? This is a better defense of dynamic types. Erlang allows for introduction of, or alteration of, code in runtime. Just like C# (via .NET), Java and the good old Dylan system. In fact, most dynamic languages do, like JavaScript and Lisp. Erlang developers seem to forget that this a quite non-unique feature. Nevertheless, introduction of new types with static typing requires explicit introspection, like using the Method class of Java. I.e., one cannot “type” for the unexpected. But, and this is an important note, dynamic typing does not save you here. You still cannot code for the unexpected. I.e., introducing types not compatible with the implicit types implied by the operations involved will still wreck the code!
This latter problem, of not being able to code for the unexpected when new code is introduced in runtime, is equally valid for alteration of code outside runtime. I.e., what happens if you suddenly decide to change the representation of a notion, such as a adding a second “e-mail” field to “customer”? You would have to go to every single point where you used those tuples, yes, all those case loci, and change the code. It is no coincidence that quite smart people introduced abstract data types
In Erlang everything is algebraic or “exposed to the outside world”. For further discussion about algebraic data types, look at this earlier post. To put it in a database-centric way: Erlang deal with non-normalized records only.Admittedly, you can embed types via accessors but that is not the “Erlang way” of doing things.
Besides these issues of dynamic types and restrictive types, I was bothered by a certain non-FP-ness of Erlang. When I tried to recall what that bother of mine was, I wrongly concluded that it must be that no anonymous function can be created. This is - obviously - not the case, one can easily do that via fun (x) -> x*2. Looking into Erlang again, I realize that it was the lack of curried functions that annoyed me.
Leaving the language for a brief moment, the execution environment is quite remarkable. So, if we can add the following two notions to Erlang, it would quickly become my new best friend:
- typing - as proposed by Wadler and Marlow
- curried functions
I will stop whining now and instead help out in making the Erlang world a better place. The beams call me!
compile time Computer Science erlang Functional Programming Language Reviews