[erlang-questions] Improving Erlang!

Richard O'Keefe ok@REDACTED
Thu Dec 2 04:38:41 CET 2010


On 2/12/2010, at 6:34 AM, Gilberio Carmenates García wrote:

> Hi all!
> 
> 
> 
> Things like this could be nice in Erlang
> 
> 
> 
> start(Type, Args)->
> 
> ChkArg = fun(Arg)->
> 
> case lists:keyfind(Arg, 1, StartArgs) of
> 
> {Arg, true}->
> 
> true;
> 
> _->
> 
> false
> 
> end
> 
> end,
> 
>                if
> 
>                               ChkArg(install)->
> 
>                                               ?MODULE:install();
> 
>                               ChkArg(debug)->
> 
>                                               appmon:start();
> 
>                               true->
> 
>                                               %% Starts the application.
> 
> 
> evo_debug_module:print([{debug, true}], "~n~nApplication: \"~p\" is
> starting...~n", [?MODULE]),
> 
> 
> evo_debug_module:print([{debug, true}], "~nType: ~p   StartArgs: ~p~n",
> [Type, StartArgs]),
> 
>                                               R =
> evo_main_supervisor:start_link(StartArgs),
> 
> 
> evo_debug_module:print([{debug, true}], "~nApplication: \"~p\" is ready.~n",
> [?MODULE]),
> 
>                                               R
> 
>                end.
> 
> 
> 
> But that is impossible

However,

start(Type, StartArgs) ->
    ChkArg = fun (Arg) ->
        case lists:keyfind(Arg, 1, StartArgs)
          of {Arg, true} -> true 
           ; _           -> false
        end
    end,
    case ChkArg(install)
      of true  -> ?MODULE:install()
       ; false ->
         case ChkArg(debug)
           of true  -> appmod:start()
            ; false -> 
	        evo_debug_module:print([{debug,true}], 
	                "~n~nAplication: \"~p\" is starting...~n",
	                [?MODULE]),
		...
	 end
    end.

*is* possible.  And for some reason, I found it much easier to
see that the debugging stuff is done when the debug flag is OFF
in this version than in the original, even when laid out neatly.

By the way, there is an EEP to allow 'un-nesting' cases like this.

It's also possible to write

start_type(StartArgs) ->
    case lists:member({install,true}, StartArgs)
      of true  -> install
       ; false ->
	 case lists:member({debug,true}, StartArgs)
           of true  -> debug
            ; false -> start
	 end
    end.

start(Type, StartArgs) ->
     case start_type(StartArgs)
       of install -> ?MODULE:install()
        ; debug   -> appmon:start()
        ; start   -> lots of debug output
     end.

Let's generalise a little.

first_true_option(Pairs, Flags, Default)
  returns the first Flag in Flags such that {Flag,true} is in Pairs,
  or Default is there is no such flag.

first_true_option(_, [], Default) ->
    Default;
first_true_option(Pairs, [Flag|Flags], Default) ->
    case lists:member({Flag,true}, Pairs)
      of true  -> Flag
       ; false -> first_true_option(Pairs, Flags, Default)
    end.

start(Type, StartArgs) ->
    case first_true_option(StartArgs, [install,debug], start)
      of install -> ...
       ; debug   -> ...
       ; start   -> ...
    end.

          
> since the ‘if’ clause only work with guards, so since
> we can not define our own guards that and many other limitations can come
> up.

And as we now see, it doesn't matter in the slightest.
Using a 'case' form instead of an 'if' means that
 - the order of the cases doesn't have to matter
 - it can be easier to see oddities, like debugging output
   NOT being in the debug case.




More information about the erlang-questions mailing list