OSCON 2008: Practical Erlang Programming

After lunch and our trip to the Apple Store, I’m sitting in Portland 256 for the Practical Erlang Programming. It’s being taught by Francesco Cesarini of Erlang Training and Consulting Ltd.

Over 90 people registered for this tutorial, and the room is almost full. Save for the handful of available chairs, I’d feel guilty about auditing it instead of attending the Real Time 3D on the Web with Open Source I had originally registered for. This will be a two and a half day course compressed into three hours. Should be fun, and useful for Kevin’s session tomorrow, Beautiful Concurrency with Erlang. After seriously considering the relative merits and general usefulness of the tutorials, I decided Erlang would be much more interesting. I had made my original choice with the equivalent of a dart board, so I don’t feel too bad about changing my mind.

The tutorial started with a quick tour of Erlang’s syntax. It looks odd, but I’ve used Lisp and ML in the past, and I’m a rather good Perl hacker, so it isn’t proving too difficult to pick up. The concept of pattern matching intrigues me. It appears to use equivalency, in the mathematical sense to handle both boolean and assignment operations with the same syntax. For example,

[A,B,C] = [1,2,3]    % A is 1, B is 2, C is 3
[A,B,C] = [1,2]      % error, size mismatch
[A,B,A] = [1,2,3]    % error, A already bound to 1
[A,B,A] = [1,2,1]    % okay, A bound to 1, then equivalent to 1

Shortly into the discussion of syntax, Francesco asked that anyone who hasn’t yet installed Erlang do so. I executed yum install erlang, which pulled in unixODBC, tcl, and tk as dependencies. Well, 45 megabytes and 45 minutes later—an impressive speed of 1 MBpm—I now have Erlang installed and ready to run. Just in time for a 10 minute break.

During this first break, we were asked to do a simple exercise in Erlang: write a module, boolean.erl, that implements b_not(), b_and(), b_or(), and b_nand(), without using the built in logical operators. I’ve been able to define the structure of the module, but I don’t know how boolean values are represented in Erlang, so I may have to wait until he gives us the answer. Vim’s syntax highlighting tells me that true and false are reserved words, so I can use those.

The solution for this involves writing a simple truth table. In Erlang, functions are subject to pattern matching in the same way that many programming languages allow for function overloading. For the logical or, we start with the basic truth table:

b_or(true,true)   -> true;
b_or(true,false)  -> true;
b_or(false,true)  -> true;
b_or(false,false) -> false.

That’s downright simple and extremely easy to grasp on a conceptual level, particularly for anyone with any background in mathematics. However, and this appeals to me as Perl hacker, Erlang allows the programmer to be lazy, but in a good way. The null variable—as I’m calling it due to the analogy with /dev/null on Unix-like systems (or undef in Perl)—_, allows a kind of lazy matching:

b_or(false,false) -> false;    % the only false case with OR
b_or(_,_)         -> true.     % any other case is true

The other functions can be written in a similar way.

Back from the break, and the population of the room has thinned very slightly. Francesco immediately jumped into conditional evaluation, starting with the case clause. I suspect this may be one of the answers to the exercise. He followed that with the if clause. I find it interesting that he’s done it in that order. In most languages, the if statement is a much simpler case (no pun intended) and is covered first, before moving into more complex territory. I think I understand why, the two clauses are implemented in a very similar fashion. I’m not sure how equivalent they are, I’d have to play with them a bit.

As with any functional language, Erlang has strong support for recursion as well as a handful of built in functions (BIFs) implemented in C to accomplish things that are difficult or impossible to do directly in Erlang. After all, at a certain point, things like date and time require system calls. Also available are convenience functions to do things like convert tuples to lists or back.

At the second, official, break—taken after an official entered the room to scold Francesco for being 15 minutes late—we were presented with two more exercises. First, to write a function, sum/1, which, given a positive integer N, will return the sum of all the integers between 1 and N. As an extension, write a function, sum/2, which, given two integers N and M, return the sum of the interval between them, first ensuring N <= M. Second, write a function, create/1, which will return the list 1 through N given N as its argument. As an extension, write a function, reverse_create/1, which does the same in reverse.

As I suspected, both exercises are perfect candidates for recursion, which is quite simple to do in Erlang:

sum(N) when N > 0 ->
    N + sum(N-1);
sum(0) ->
    0.

The simpler list creation function is actually the second, and is solved similarly, but by accumulating a list instead of adding to a sum (which is, actually, also a method of accumulation):

reverse_create(0) ->
    [];
reverse_create(N) ->
    [N|reverse_create(N-1)].

The first thing I notice is, again, how mathematical Erlang is. The solution is written in exactly the same way I do it when I’m jotting down notes while thinking about how to solve the problem. To me, the syntax is quite elegant.

After going over the solutions to the exercises, we moved into concurrency. As with most languages worth using, Erlang has a spawn() BIF, used to create processes. What’s interesting about spawning processes in Erlang is that the function to do it does not take a system command. Rather, it takes another Erlang function to run. It’s quite a bit more elegant (there’s that word again) than the equivalent fork() dance done in most imperative languages.

Communication between Erlang processes is done via message passing; data is never shared. As with everything else, the method for doing so is quite elegant: Pid2 ! {self(), foo}. Okay, maybe someone has to be me to find that elegant.

The whole process concept in Erlang is quite nice and, again, elegant. It’s plain that it is the primary method by which systems in Erlang are designed. So far, though, we’ve only seen trivial examples. That’s okay, because this is only a three hour tutorial. However, as Larry Wall once said about Perl: It makes the easy things easy and the hard things possible. It’s a good litmus test for any language. It’s far too early for me to pass any judgment on Erlang. I’d like to use it in anger sometime, to see how it performs for me. Perhaps I can get my local Perl Mongers interested in chatting about it.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">