Technology and Software

First Impact with the Syntax of the Erlang Language

This is a report of my first impact with the syntax of the Erlang language.

I’m familiar with C, shell, Perl, Java, JavaScript and Ruby. I’m also a strong believer that languages are made for people and not for computers. They must be easy to read and to write. They must not be cluttered with signs: the noise to signal ratio must be low. Luckily this is where modern languages are heading to as they’re getting rid of braces and compilers and interpreters are using the available CPU power to understand where statement end without forcing us to tell it them with ; characters.

This is a “first impact” report, so I’m sure that there are lots of things I didn’t understand and I might be very wrong on some points. Nevertheless, there is only one chance of making a good first impression and I think that languages should strive for making a good one by adopting the kind of syntax that developers are demonstrating to like.

Here we go!

  • All variable names in Erlang must start with an uppercase letter. It looks very old style. It tastes of BASIC interpreters of the ’80s. I understand that variables are actually constants (they are “single assignment variables”) and atoms (much like Ruby’s symbols) start with a lowercase but it’s unsatisfactory.
  • The _ anonymous variable is good. It looks like a hack but writing this code in Perl is a waste of time
($skip1, $var, $skip2) = split(/ /)

and Ruby’s

var = str.split(/ /)[1]

is less descriptive than Erlang’s

(_, Var, _) = split
  • Ending each statement with . looks redundant. Why can’t one design a parser that understands when a statement ends? Ruby demonstrates that’s possible. Furthermore using a . is a bad choice because expressions like R = 5. (an integer) and R = 5.0. (a float) look very strange with the same character doing two different things (ok, Ruby suffers from the same problem with 5.0.to_i). It could be habit but ; is a more sensible choice for an expression terminator.
  • Atoms are good for the very same reason Ruby’s symbols are good. No more having to assign values to the constants which we only care about for their name. That’s the job of the compiler.
  • Nested tuples look like JSON, which is good. The example
1> F = {firstName, joe}.
{firstName,joe}
2> L = {lastName, armstrong}.
{lastName,armstrong}
3> P = {person, F, L}.

yields

{person,{firstName,joe},{lastName,armstrong}}

which is strikingly similar to

{person: {firstName: joe , lastName: armstrong }}

By the way

{_,{_,Name},_} = {person,{firstName,joe},{lastName,armstrong}}

extracts joe from the tuple.

  • Strings as array of integers are OK as this is what they really are but the shorthand $a for the integer which represents the character a looks like a hack. How do you apply that to arbitrary characters regardless of their encoding?
  • The – character as in -module or -export is ridiculous. I understand the reason # for C’s #define and #include (the preprocessor) but no modern language should do that.
  • Having to declare the number of arguments of a function as in -export([factorial/1)] is also ridiculous. OK, there might be other functions with the same name and different number of arguments in the same module but I’m doing the job of the compiler and this is very wrong. There must be very good reasons for this choice, but this is not the way to design languages nowadays. We’ve got enough CPU and enough practice to let us write simpler code. This code
-module(math2).
-export([double/1]).
double(X) ->
  times(X, 2).
times(X, N) ->
 X * N.

should have been

module math
export double(X) ->
  times(X, 2)
times(X, N) ->
  X * N

No -, no useless () and [], no .

  • The -> sign is an improvement over mainstream languages. They use things like these to define methods and functions
function times(x, n) { ... } // JavaScript
function times($x, $n) { ... } // PHP
int times(int n, int x) { ... } // C
def times(x, n) do ... end # Ruby
public int times(int x, int n) { ... } // Java
sub times { my $x = shift; my $n = shift; ... } # Perl
times () { x = $1; n = $2; ... } # bash

which are all more verbose than Erlang. However -> could be improved. Practice demostrated that two characters combinations are worse than single characters. PHPs -> is painful compared to other languages’ . and Ruby is switching to JavaScript’s : from its own => sign for defining key, value pairs in hash tables.

  • Pattern matching with atoms is good. It can be used to implement object orientation in a different and maybe more descriptive way, as in
area({square, Side}) ->
  Side * Side;
area({rectangle, X, Y}) ->
  X * Y;

1> area({square, 5}).
25
  • Message passing to processes is extremely good. The echo demo program
-module(echo).
-export([start/0, loop/0]).
start() ->
  spawn(echo, loop, []).
loop() ->
  receive
    {From, Message} ->
      From ! Message,
      loop()
    end.

is very small and clear: From is a process, Message is the message and From ! Message sends message to the from process just after receive {From, Message} has received it from the caller process (From), which is something like this.

import(echo).
P = echo:start().
P ! "hi there!".

Very easy to do.

That was the end of my first hand on session with Erlang. It was based on the example in the freely available excerpts of Concurrent Programming in Erlang and Programming Erlang.
My first impression is that the language has some very good points but lacks some polish. To be fair, Erlang first appeared in 1986, a time when developers where used to all those signs we’re looking at as clutter now. It probably looked like a terse language back then.

Standard