Wed, 04 Apr 2007

Learning Erlang.

The decision has been made, I'm going to learn the Erlang programming language. The main reason for this decision is that Erlang does one thing better than any other programming language I am aware of; parallel, concurrent and distributed processing.

The big problem with parallel and concurrent processing in other languages is that the standard method of communication between threads in most languages is shared data protected by mutexes or semaphores which are difficult to get right when there are a lot of threads or a lot of data to be protected. The standard solution to the problems of dealing with parallelism simply doesn't scale well.

Erlang excels at parallel processing because it forgoes the use of semaphores, mutexes and other synchronisation primitives. It replaces these shared data synchronisation methods with message passing; a much simpler mechanism which is much easier to reason about and much harder, maybe even impossible, to get wrong.

When learning, a new language, my usual approach is to write lots of small demo programs, with each one demonstrating a different feature. These programs come in really useful later as an easy to reference catalogue of language features.

Here's my first complete Erlang program, which takes any number of integer parameters on the command line and prints the factorial of each one:

  #!/usr/bin/env escript

  -export ([main/1]).

  % Naive factorial function.
  fac (0) -> 1 ;
  fac (N) when N > 0 -> N * fac (N - 1).

  % Function to print the factorial of each list element.
  print_fact_list ([]) -> ok ;

  print_fact_list ([Head | Tail]) ->
      % Convert the Head from a string to an int.
      Int = list_to_integer (Head),
      % Calculate the factorial.
      Fact = fac (Int),
      % Print the result.
      io:format ("fac ~w : ~w~n", [Int, Fact]),
      % Call the function recursively with the tail of the list.
      print_fact_list (Tail).

  % Main function, accepts a list of strings contain argv [1], argv [2] etc.
  main (List) ->
      case length (List) of
          0 -> io:format ("Usage : factorial.erl <number>\n") ;
          _ -> print_fact_list (List)

To me, this Erlang code looks a little like Ocaml and a little like Prolog which I used briefly at university over a decade ago. A couple of things to note:

To run this program requires Erlang, which on Debian and Ubuntu means the packages erlang, erlang-base, erlang-dev and erlang-manpages. It also uses escript, which comes standard with Erlang R11b4 and can be obtained here for earlier versions (Ubuntu Feisty has R11b2). Escript allows Erlang code to be run as a script, just like Python or Ruby.

The output of this program when passed the numbers 10, 20 and 30 results in the following output:

  fac 10 : 3628800
  fac 20 : 2432902008176640000
  fac 30 : 265252859812191058636308480000000

Yep, Erlang uses arbitrary precision integers by default. Thats pretty cool.

Posted at: 23:07 | Category: CodeHacking/Erlang | Permalink