Exception handling idioms

Ulf Wiger ulf@REDACTED
Thu Aug 25 21:13:19 CEST 2005


Den 2005-08-25 20:21:56 skrev Vance Shipley <vances@REDACTED>:

> What I do is to write the gen_server like this:
> handle_call({Atom, Int, List}, _, State)
>         when is_atom(Atom), is_integer(Int), is_list(List) ->
>     ...
>     {reply, Result, State};
> handle_call(_, {Pid, _Tag}, State) ->
>     exit(Pid, badarg),
>     {noreply, State}.

My preference is to do this:

handle_call({Atom, Int, List}, _, State)
          when is_atom(Atom), is_integer(Int), is_list(List) ->
      ...
      {reply, Result, State};
  handle_call(_, _, State) ->
      {reply, badarg, State}.


and then a custom call/1 function:

call(Request) ->
    case gen_server:call(?SERVER, Request) of
       badarg ->
          erlang:error(badarg);
       Reply ->
          Reply
    end.

You can substitute 'badarg' for some other value,
as long as it cannot be confused with a good reply.
One way to ensure this is to wrap the replies:

case gen_server:call(?SERVER, Request) of
    {error, Reason} ->
       erlang:error(Reason);
    {reply, Reply} ->
       Reply
end.


The advantages of doing it this way are:
- if the client is trapping exits, the call
   function must wait for a possible EXIT message.
   Then, the error indication will look different
   depending on the trap_exit flag.
- erlang:error/1 produces a call backtrace, which
   identifies the error nicely as being in the call
   function.
- If the client function is re-implemented to do
   the job locally, without contacting a server,
   the exception is already generated as if it were
   a locally executed job.

/Uffe
-- 
Ulf Wiger



More information about the erlang-questions mailing list