Set out today to extend BeepBeep, but got hung up for time writing a module that I’m hoping to use in the extension.

Oh well, it may be useful in testing other web servers/frameworks as well. With more work it might also provide a decent start toward an application involving personal contacts.

Here it is warts and all:

names.erl

-module(names).

-export([init/0, insertName/5, getNames/0, formalName/1, firstName/1, lastFirst/1]).

-include_lib("stdlib/include/qlc.hrl").

%%% Database record structures for names

-record(names,
        {last,
        honorific,
        first,
        middle,
        suffix}).

% NOTE: honorific is Mr. | Mrs. | Ms, etc.
% NOTE: suffix is Jr. | III | esq. etc.

%%% Database functions

%%% Utils

init() ->
   %% Initialize database
   mnesia:create_schema([node()]),
   mnesia:start(),
   mnesia:create_table(names,
       [ {type, set},
         {disc_copies, [node()] },
         {attributes,
              record_info(fields,names)} ]).

%%% Insert functions

insertName( Honorific, First, Middle, Last, Suffix) ->
   %% Add a name item to database
   Fun = fun() ->
      mnesia:write(
      #names{last = Last,
             honorific = Honorific,
             first = First,
             middle = Middle,
             suffix = Suffix
           })
           end,
      mnesia:transaction(Fun).

%%% Select functions by last name

getNames() ->
   %% Select list of names items from database
   mnesia:transaction(
   fun() ->
      qlc:eval( qlc:q(
        [ X || X <- mnesia:table(names) ]
      ))
   end ).

getName(Last) ->
   %% Select a name by last name from database
   %% NOTE: Doesn't account for duplicate last names
   mnesia:transaction(
   fun() ->
      qlc:eval( qlc:q (
          [X || X %lt;- mnesia:read({names, Last})]
               ))
      end ).

%%% Name formatting functions

formalName(Last) ->
   %% Given last name, return formal name
   %% NOTE 1: Doesn't account for duplicate names
   %% NOTE 2: Doesn't deal with empty fields
   [Name|_] = element(2,getName(Last)),
   {_, Last, Honorific, First, Middle, Suffix} = Name,
   FormalName = lists:append(Honorific, " ")  ++
                lists:append(First, " ") ++
                lists:append(Middle," ") ++
                lists:append(Last, " ") ++
                Suffix,
   FormalName.

firstName(Last) ->
   %% Given last name, return first name
   %% NOTE 1: Doesn't account for duplicate names
   %% NOTE 2: Doesn't deal with empty fields
   [Name|_] = element(2,getName(Last)),
   {_, _, _, First, _,_} = Name,
   First.

lastFirst(Last) ->
   %% Given last name, return full name last name first
   %% NOTE 1: Doesn't account for duplicate names
   %% NOTE 2: Doesn't deal with empty fields
   [Name|_] = element(2,getName(Last)),
   {_, Last, _, First, Middle, Suffix} = Name,
   LastFirst = lists:append(Last, ", ") ++
               lists:append(First, " ") ++
               lists:append(Middle, " ") ++
               Suffix,
   LastFirst.

Here’s how to use it:

From console

    ~$ erl
    blah blah

    1> c(names).
    2) names:init().
    3) names:insertName(“President”, “Barack”, “Hussein”, “Obama”, “”).
    4) names:fromalName(“Obama”).

I’m sure there’s an elegant way of dealing with empty fields in formalName/1, firstName/1, and lastFirst/1; indeed a more elegant way to write these functions altogether. But it works for me now and I’d need more time and a clearer head to figure it out.

Maybe a lurking wizard can show us the way.

So why did it take me some four hours to write this simple module?

1) My inexperience with Erlang
2) Skimpy and (to me) confusing Mnesia documentation.

I’m working on issue 1 and I’m not going to complain about issue 2 until I’m in a position to fix it. On the other hand, I can certainly pray that someone gets to it before I do. Simple examples starting with all the basic CRUD functions would be a good start.

If you have a low threshold for frustration, you’ll know that it’s not easy being an Erlang newbie. But I ran across this blog post recently. It puts things in perspective admirably.

http://www.postneo.com/2007/08/26/there-is-an-erlang-community-its-just-smaller-than-youre-used-to

Maybe if we work really really hard we can help flag and stamp out all those little pesky issues that impede our climb up the Erlang learning curve… make things easier for newbies even greener than we are.

Hope to get back to BeepBeep in my next post.

See ya’.

Just ran across another blog devoted to poking around Erlang:

http://ayende.com/Blog/archive/2008/09/24/reading-erlang-inspecting-couchdb.aspx

Oren Eini explores CouchDB clause-by-clause. I’m looking forward to learning much.