Erlang: The problem with being "new"

2nd of June 2008

So you spend 5/10 years learning X, but start to think it might not be the best solution for every problem, You have heard Y is good for solving your new problem, so you give it a shot, skim over some blogs, maybe even spend an afternoon learning it. After while you get fustrated, things that you can do easily in X are suddenly hard and fustrating in Y, you cant recognise the wierd interface. Conclusion: it must be a terrible language / application / etc.

One of the most popular opinions I find on Erlang is that it looks like an amazing platform, but not a very nice language. Since I had a similiar opinion when coming to Erlang (from primarily PHP and Java), I thought I would post comparable snippets to show why I now enjoy programming in Erlang.

Problem:

Code a simple chat message handler, define a simple function that takes parsed input, and calls the function relating to that command. if the message isnt one of the valid format, throw an exception. The 3 valid inputs in both languages are :

Erlang :                           PHP : 
handle({enter,"user"})             handle(array(ENTER,"user"))
handle({leave,"user"})             handle(array(LEAVE,"user"))
handle({message,"user","message"}) handle(array(MESSAGE,"user","message"))

PHP Solution :

(check the comments for Jon Hohle's version, it is much more elegant)
define("ENTER",   1);
define("LEAVE",   2);
define("MESSAGE", 3);

function handle($cmd)
{
  if(is_array($cmd) && ($count = count($cmd)) > 1)
  {
      if($cmd[0] == ENTER && $count == 2) 
        return enter($cmd[1]);
      else if($cmd[0] == LEAVE && $count == 2) 
        return leave($cmd[1]);
      else if($cmd[0] == MESSAGE && $count == 3) 
        return message($cmd[1],$cmd[2]);
  }
  throw new Exception('Invalid Message');
}

Erlang Solution :

handle({enter,User})       -> enter(User);
handle({leave,User})       -> leave(User);
handle({message,User,Msg}) -> message(User,Msg);
handle(_)                  -> throw("Invalid Message").

The example illustrates a small benefit of pattern matching which is at the heart of Erlang. Some things new users might see as 'warts' are often powerful features, and a few hours introduction into a language is never going to match the cumulative experience gained in years of writing applications.

Comments


Tom Wesson

Jun 1, 08
// smallest i could come up with -- lacks exact array size checking

function handle($cmd) {
  try {
    switch ( $cmd[0] ) {
      case 1:  return enter ( $cmd[1] );
      case 2:  return leave ( $cmd[1] );
      case 3:  return message ( $cmd[1], $cmd[2] );
    }
  } catch(e) { }
  throw new Exception ( 'Invalid Message' );
}

Justin

Jun 2, 08
The normal way you'd write this in python, is to separate the code from the data, like so.
ENTER   = 1
LEAVE   = 2
MESSAGE = 3

def handle_enter(user):
    print 'enter', user

def handle_leave(user):
    print 'leave', user

def handle_message(user, msg):
    print 'message', user, msg

handlers = {
    ENTER:    handle_enter,
    LEAVE:    handle_leave,
    MESSAGE:  handle_message,
}

def handle(cmd, *args):
    f = handlers.get(cmd)
    if not f:
        raise Exception("Invalid Message")
    return f(*args)


It takes a little more work up front, but you can see the actual handler function is super simple. The erlang approach is nice too, their automatic creation of atoms makes you have to do less work. For python a common thing is to just use strings for the message types, then you don't even need the dictionary.

Anonymous

Jun 2, 08
You've been reddited.
>
...handle({message,User,Msg}) -> message(User,Msg);

handle(_) -> throw("Invalid Message").

Is this last line idiomatic Erlang?

Side note: Your blog is very hard to read in Opera.

Dale

Jun 2, 08
Thanks Ill check it in opera, most of the frontend stuff I have coded recently just works in opera so i've been lazy in testing.

the throw itself is not idiomatic, I would usually leave it out and imagine most erlangers would, without it erlang would throw its own exception that looks like
** exception error: no function clause matching 
module:handle(your,"madeupparams")
which is easily understandable, I occasionally throw exceptions when a function can be wrapped in transactions / first class functions and I want to be very specific about point of failure. its usually not needed though, I mostly put it in to match the PHP

the _ is just a match all / dont care expression

**edit : fixed opera, must remember to validate new posts

josh

Jun 2, 08
SML and Scala are nice, too. They also have a type system that cmpliments the pattern matching. Patching matching is the one ring to rule them all.

Michael Mrozek

Jun 2, 08
I think I actually prefer Haskell's pattern matching to Erlang's, although they're both awesome, and Erlang's atoms make things hugely convenient

Jon Hohle

Jun 2, 08
It looks like Java affected your PHP too much. switches in PHP aren't limited to scalar types like they are in C derivatives:

define('ENTER',   1);
define('LEAVE',   2);
define('MESSAGE', 3);

function handle(array $cmd) {
  switch (array(array_shift($cmd), count($cmd))) {
    case array(ENTER, 1):   $handler = 'enter';   break;
    case array(LEAVE, 1):   $handler = 'leave';   break;
    case array(MESSAGE, 2): $handler = 'message'; break;
    default: throw new Exception('Invalid Message');
  }
  return call_user_func_array($handler, $cmd);
}
You get the array check for free with argument type hints, and the array size checking is done by the switch. In fact, adding a new case is about the same amount of code as your Erlang example (though the boiler plate is much larger) - just one additional line. The arity check is explicit, however, unlike the Erlang example, where arity is implied by pattern matching.

Don't get me wrong; I'm not trying to say PHP is as flexible or convenient, or as elegant as Erlang. I would never say PHP is a beautiful language. Your PHP example just doesn't take advantage of the available language features.

Jon Hohle

Jun 2, 08
er, i guess the pre tags were unnecessary.

Dale

Jun 2, 08
Jon, I am impressed, I knew type hinting was coming to PHP, but bever realise it was introduced into php 5, I knew switch was more flexible, but I also didnt realise it was that flexible. Its a construct I used to avoid in php/java etc (the opposite of erlang, in which Ive almost never used if and always use case)

Thats certainly the most elegant PHP version ive seen. It was never an intention to make a PHP vs Erlang argument, I still like PHP, and dont think there is a language I have used that isnt the best in some situations, Its just a shame to see people dismiss languages like Erlang / Haskell etc purely due to being unfamiliar with the syntax.

(I will put instructions / rewrite the formatter for code in comments tomorrow, this is a new blog, and its obviously not very good)
For any programming languages X and Y, there are an arbitrary number of problems which, when restricted enough, can be solved much more nicely in language X, and vice versa.

I really doubt Erlang is anywhere near as terrible as PHP, but this example seems pretty meaningless to me. There are many problems which would make PHP appear just as superior to Erlang.

Jon Hohle

Jun 2, 08
Erlang looks really interesting. In fact, before I saw your post this morning, I watched Bob Ippolito's C4 talk which is why I clicked on your reddit link to begin with.

From what I've seen, I really like Erlang's syntax; though I must admit, I really know nothing about the language. Hopefully more blog posts like this one will convince me to look into it further ;)

Dale

Jun 2, 08
James, of course, I could being out a lot of patterns PHP is better than Erlang and vice versa. It just seems a lot of people think that erlang etc are only used only for the benefits their platform / architecture brings (side effect free / reliability), and put up with the syntax details because for now they have to, which isnt the case from my view.

Jon, good to hear, it really is an amazing platform wrapped in a pretty nice little language.

Post a Comment


Name :

Url :

Comment :
html is enabled, you may post links / images and basic formatting, styling is permitted.

four plus zero is :
Simple check against spamming robots