[erlang-questions] A style question

Richard O'Keefe <>
Tue Feb 16 03:44:00 CET 2010


On Feb 16, 2010, at 12:05 AM, Joe Armstrong wrote:
> It was written in the scrolls, by the old ones, possible by the great
> Daniel D.McCracken himself,
> that I,J,K,N were always integers, R was real and so on.

The classic Fortran "INteger letters" rule:
if it begins with I-N it's integer, A-H or O-Z it's real (=float),
and if you want any other type you must declare it.
I knew a generation of programmers who were scarred by IBM 1130
Fortran, which restricted identifiers to 5 letters+digits.
>
> Having written about 100K lines of FORTRAN (blessed be it's memory)

Fortran is alive and well, and contains a fairly clean "structured
programming" sublanguage.  It's quite a decent language for writing
number-crunching code.

> I hate long variable name because they clutter up the code.
> So I use "abbreviated camel variables + comments"
>
>  %% UTF = UpdateTheFebblerokker
>   UTF = fun() -> ...
>   Mnesia:transaction(UTF)
>
>  "UpdateTheFebblerokker" has 21 characters. So the first version uses
> 2*21 (42) characters to communicate the
> name.
>
>  The second version uses 21 + 3 * 3 (30) characters to communicate  
> the name.
>  So my version is 12/42 (29%) more abstract).

If we use the inline version with a comment,
	mnesia:transaction(fun () -> % Update the febblerokker
	    ...
	end
it's even more concise.  And there is no acronym puzzle for the
reader to solve.  (Doesn't UTF mean "Unicode Transmission
Format" or something?  Did I read that right or was it a reference
to UHT milk or UFOs?)

Do you read UTF aloud as you-tee-eff or, to avoid confusion,
do you read it aloud as update-the-febblerokker?

When someone else reads the comment, do they not go looking
for the binding of UpdateTheFebblerokker to find out what it
is that the comment is saying UTF is equal to?  I would!
>

> You'd also need a comment explain what a Febblerokker is. I think it's
> some kind of
> DoppleKlonkerSubWogiLuple but this is from memory, it's a long time
> since I worked with this kind of
> stuff.

You have not explained why this is an an improvement on the
inline style, which allows a comment of whatever length you
require, in grammatical (choose your natural language here)
with references as needed, and _doesn't_ introduce PFTHRTS.
(Puzzles For The Hapless Reader To Solve.)

Let's try a concrete example, from the Erlang/OTP sources.

mnesia_open({table_exist,Name},_Nodes,_RecName,_Attr,_Type,clear) ->
     ?vtrace("[mnesia] database ~p already exists; clear content", 
[Name]),
     Pattern = '_',
     F = fun() ->
                 Recs = mnesia:match_object(Name,Pattern,read),
                 lists:foreach(fun(Rec) ->
                                        
mnesia:delete_object(Name,Rec,write)
                               end, Recs),
                 Recs
         end,
     case mnesia:transaction(F) of
         {aborted,Reason} ->
             exit({aborted,Reason});
         {atomic,_} ->
             {mnesia,Name}
     end;


Try it another way:

mnesia_open({table_exist,Name}, _Nodes, _Record, _Attr, _Type, clear) ->
     ?vtrace("[mnesia] database ~p already exists; clear content",  
[Name]),
     case mnesia:transaction(fun () ->
             %% find all records in table Name and delete them.
             Recs = mnesia:match_object(Name, '_', read),
             _ = [mnesia:delete_object(Name, Rec, write) || Rec <-  
Recs],
             Recs
	 end
       of {aborted,Reason} ->
              exit({aborted,Reason})
        ; {atomic,_} ->
              {mnesia,Name}
     end.

(I'm so ignorant about Mnesia that I'd have used
  mnesia:clear_table(Name) to empty out a table.)

What have we lost by eliminating the name "F"?
After all, no such name was used in the call to
lists:foreach/2, where due to the unfortunate argument
order of lists:foreach/2, it would have been useful.

In fact for me, having the fun in place suddenly made it
possible for me to see that there was no point in having
it return Recs.  So now I can write it as

mnesia_open({table_exist,Name}, _Nodes, _Record, _Attr, _Type, clear) ->
     ?vtrace("[mnesia] database ~p already exists; clear content",  
[Name]),
     case mnesia:transaction(fun () ->
             %% find all records in table Name and delete them.
             Recs = mnesia:match_object(Name, '_', read),
             _ = [mnesia:delete_object(Name, Rec, write) || Rec <-  
Recs],
             ok			% THIS LINE CHANGED
	 end
       of {aborted,Reason} ->
              exit({aborted,Reason})
        ; {atomic,_} ->
              {mnesia,Name}
     end.

Previously I found that hard to see because the 'fun' and
the mnesia:transaction were *disconnnected*.





More information about the erlang-questions mailing list