[erlang-questions] Some functions must return values other may do so...

PAILLEAU Eric eric.pailleau@REDACTED
Sun Aug 16 23:48:51 CEST 2015


Hi,

Use of macros could be easy for coding.
1) Must/May/Might are uppercase in the code, easy to see.
2) switch between must/may/might is easy without any code change except 
macro name.

Regards
_____________________________________________________________________________
-module(might).

-export([test_must/1, test_may/1, test_might/1]).

-define(MUST(M), case M of
                       {ok, X}    -> X;
                       {error, E} -> exit({?MODULE, ?LINE, 
io_lib:format("~s",[??M]), E})
                  end).

-define(MAY(M), M).

-define(MIGHT(M), (catch ?MUST(M))).


test_must(F) ->  ?MUST( file:open(F, [read]) ) .

test_may(F)  ->  ?MAY( file:open(F, [read]) ).

test_might(F) -> ?MIGHT(file:open(F, [read])) .
_____________________________________________________________________________

1> might:test_must("/tmp/none").
** exception exit: {might,15,["file : open ( F , [ read ] )"],enoent}
      in function  might:test_must/1 (might.erl, line 15)

2> might:test_may("/tmp/none").
{error,enoent}

3>  might:test_might("/tmp/none").
{'EXIT',{might,20,["file : open ( F , [ read ] )"],enoent}}


Le 15/08/2015 16:56, Joe Armstrong a écrit :
> For a while now I've adopted a convention for naming functions
> which I find rather useful, so I thought I'd discuss it here,
> (it's a kind of RFC-2119 lite notation :-)
>
> Rule1: Functions which return {ok,X} | {error,W} are called may_<name>
>
> Rule2: Functions which return a value or raise an exception are called
> must_<name>
>
> I use a small interface library which enforced this, for example,
> I have a wrapper round file:open which looks like this:
>
>     must_open_file(File, Mode) ->
>         case file:open(File, Mode) of
>             {ok, X} ->
>                X;
>             {error, E} ->
>                exit({most_open,File,in_mode,Mode,failed,E})
>         end.
>
>     may_open_file(File, Mode) ->
>        file:open(File, Mode).
>
> Using this convention
>
>    dict:find(Key, D)  should be called may_get(Key, Dict)
>    dict:fetch(Key, D) should be renames must_get(Key, Dict)
>
> With this convention I can write code like:
>
>     must_sequence() ->
>        Handle = must_open_file("some_file_which_i_know_must_exist.txt", [read]),
>        Data = must_read_file(Handle),
>        must_write_file("fileout", Data).
>        must_close_file(Handle).
>
> Or, when "file" might exist, I'd write:
>
>      test1() ->
>          case may_open_file("file", [read]) of
>             {ok, Handle} ->
>                   ...
>             {error, _} ->
>                   .. do something else ...
>          end.
>
> may_<name> function are *always* called from case statements
> must_<name> function are called in linear code with no case statements
>
> I usually also wrap the top level call to a sequence of
> must_* functions in a catch, something like:
>
>       top() ->
>           case (catch must_sequence()) of
>               {'EXIT', What} ->
>                  ... do some recovery stuff ...
>               Ok ->
>                  Ok
>          end.
>
> Code written using the must/may convention seems to be extremely easy
> to read, since from the name of the function I don't have to speculate
> as
> to the form of the return value - I know immediately if the function
> will raise and exception on error or give an ok/error return value.
>
> Cheers
>
> /Joe
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
>




More information about the erlang-questions mailing list