[erlang-questions] Variable naming conventions

Richard O'Keefe ok@REDACTED
Wed Apr 7 08:36:23 CEST 2010


On Apr 5, 2010, at 3:26 AM, Garrett Smith wrote:
(a) Multiple "versions" of a value named in the same scope.

     I can tell you something worse that numeric suffixes, and that's
     *no* annotation, so that you have to trace through the control
     flow to find out which version you are looking at.

> handle_call(_, #state{name=Name}=State) ->
>    UpdatedName = strip_white_space(Name),
>    {noreply, State#state{name=UpdatedName)}}.

This can be written as

     handle_call(_, State) ->
         {noreply, State#state{name =  
strip_white_space(State#State.name)}.

You could even refactor it as

     state_sans_white_space_in_name(State = #state{name = Name})) ->
         State#state{name = strip_white_space(Name)}.

     handle_call(_, State) ->
         {noreply, state_sans_white_space_in_name(State)}.

The real problem of repetition here is
	State, state, State, State
	name, Name, name,

So here is a general pattern: we have a variable V which is an instance
of record R and we want to update field F from old value O to new  
value N.

	-define(update(V,R,F,O,N), (#R{F=O}=V, V#R{F=N})).

	handle_call(_, State) ->
	    {noreply, update(State, state,name, O, strip_white_space(O))}.

Or a higher order function:

	update@REDACTED(F, State = #state{name = Old})
	  when is_function(F, 1) ->
	    State#state{name = F(Old)}.

	handle_call(_, State) ->
	    {noreply, update@REDACTED(fun strip_white_space/1, State)}.

> The other frustrating case -- and far more so -- is something like  
> this:
>
>  Name = case get_name() of
>    undefined -> "";
>    {ok, NameValueReturnedByGetName} -> NameValueReturnedByGetName
>  end
>
> (I'm calling this "leakage" because I'd probably just call it Name if
> it didn't leak. While that'd be clunky, it at least says what I think
> it should.)

But you can perfectly well write

     case get_name() of undefined -> Name = "" ; {ok, Name} -> ok end

There is some feeling in the Erlang community against exporting variable
bindings from 'case'.  I reckon sometimes it's a good idea, sometimes  
not.

In cases like this where you are supplying a "default" for a function
that didn't have one, again, write a function.

	get_name(Default_Name) ->
	    case get_name()
	      of undefined -> Default_Name
	       ; {ok, Name} -> Name
	    end.

and then use

	Name = get_name("")

Presto chango, no leakage.  If you like longer names,
get_name_with_default/1 might be clearer.

Or if you have several functions with a common
undefined | {ok, X} result type, you could use

	with_default(undefined, Default) -> Default;
	with_default({ok, Value}, _)     -> Value.

	    Name = with_default(get_name(), "")



> I know I can refactor this into a function and solve the problem, but
> of course there are cases where I don't want to.

So of course the best thing to do is to show us one of those cases.

There's an "old" Erlang style that goes back before Erlang had
funs at all.  (And there were good reasons to stay with a first-order
language.)  With the introduction of funs, it is possible to move
closer to an ML or Haskell style.




More information about the erlang-questions mailing list