Monthly Archives: December 2012

A Different Thought Process: OOP to Erlang

I’ve been dabbling in functional programming lately, more specifically in erlang. I am familiar with recursion. I do use recursion on occasion when code simplicity outweighs the possible performance cost. I am reading Erlang Programming by Francesco Cesarini & Simon Thompson. I am enjoying the book, although I’ll admit I’m not very far into it. I would like to share a realization that I had during one of the exercises: don’t think in objects, think pattern matching.

The exercise consisted of creating a simple database. The underlying structure was a key/value pair contained in a list. The interface consisted of new, destroy, write, delete, read, and match. I am going to focus on the read(Key, Db) function, where Db is the list obtained from calling new. After adding data consisting of key/values, I would call the read function with the specified Key.

My initial implementation was as such:

read(_Key, []) -> {error, instance} ;
read(Key, Db) -> 
  [Head | Tail] = Db,
  case Head of
    {Key, Data} -> {ok, Data} ;
    {_,_} -> read(Key, Tail)
  end.

I want it to be known that this does work. It looks horrid, but it does work. Imagine if this were a more complex operation? My problem at the time was thinking the Db argument was a list. I would then pull out the Head (first item in the list) and Tail (remaining list items) once in the function. This was so wrong of me. I was thinking OOP and not pattern matching.

When I remembered Pattern Matching can be used for deep matches. I refactored the read operation to three lines.

read(_Key, []) -> {error, instance} ;
read(Key, [{Key, Data} | _Tail]) -> {ok, Data} ;
read(Key, [_ | Tail]) -> read(Key, Tail).

The first implementation was using pattern matching. The matches were based on an empty list and a non empty list. The refactored code pattern matches on an empty list, a non empty list where the first item contains the key we were looking for, and a non empty list where the first item’s key did not match.

When pattern matching with functions in erlang, it seems less about what the arguments are, and more about what you want them to be.