[erlang-questions] When to return {ok, Value} or just the Value

Ladislav Lenart lenartlad@REDACTED
Wed Nov 16 11:21:21 CET 2011


Hello.

Richard's explanation seems much more consistent to me.

I would call erlang:error/1 in both examples you provide.

To me, division by zero is no different than any other
error caused by a bad input (e.g. an atom instead of a
number). In all these cases the caller is responsible for
the correct input.

This is even more evident in case of factorial/1 because
I would write it like this (please ignore the inefficient
implementation):

factorial(0) -> 1;
factorial(1) -> 1;
factorial(N) when N > 0 -> N * factorial(N - 1).

As you can see, negative N would cause a function_clause
*error*.

In other words, all these cases represent bad usage of
the functions (API). They should not happen. Also, the
stacktrace (provided only by the error) is helpful in
pursuit of the real culprit...


Just my 2c,

Ladislav Lenart


On 16.11.2011 10:04, Joe Armstrong wrote:
>
>
> On Wed, Nov 16, 2011 at 1:38 AM, Richard Carlsson <carlsson.richard@REDACTED <mailto:carlsson.richard@REDACTED>> wrote:
>
>     On 2011-11-15 22:56, David Mercer wrote:
>
>         What criteria should I use in deciding whether an error should terminate the
>         process (exit) or not (error)?  Either way, if not caught, it terminates the
>         process, and, if caught, it doesn't.  If I'm writing a function and there is
>         an error, why would I decide, "this error should terminate the process" and
>         "this error should not"?  The function usually isn't even process-aware;
>         it's a function that does something; or not, and then it errors.  It doesn't
>         care whether it is part of a supervision tree or linked web of processes; it
>         just wants to signal an error, and let the caller decide whether to catch it
>         or crash.  Why is the erroring function giving a hint to the caller as to
>         how to handle its errors, and, really, what does the hint even mean, since
>         it seems to make no effective difference?
>
>
>     Effectively, no, any uncaught exception of any kind will terminate the process. But using exit(X) indicates that you know this code is running as part of a process which should at this point die
>     unless someone for some even better reason decides to catch the exception, and the value X is something that some other process might be looking for in an 'EXIT' or 'DOWN' message. And of course,
>     'exit(normal)' has the special meaning of terminating the process just as if it had simply returned from its initial call - any linked processes which are not trapping exit signals will stay alive
>     if they receive an exit signal with the reason 'normal', while any other exit reason will cause them to fail and propagate the same signal. In any case, a process terminating due to an explicit
>     exit(X) is considered to be a controlled termination, and the Erlang error logger will not log this.
>
>     Using error(X), on the other hand, says that you just want to signal an error but with no particular intent of ending the process; it is not possible to proceed, but the caller might want to catch
>     the exception and try something else. Your code has no opinion on what to do on a process level. An uncaught error (or throw) will terminate the process and also bring down any non-error-trapping
>     linked processes, and the error logger will log the crash as an anomalous process termination.
>
>
> I have a problem with this - when you write library routines, or just write a function
> I'm not normally thinking about the process(s) in which the function is called.
> Whether or not the process exits is a decision made by the caller of a function and not
> the function itself. You can say exit(..) in a function but the caller might trap the
> exit and not die. Therefore if the reader of a function interprets exit(..) as meaning the
> process should die, then they might get a nasty surprise later.
>
> I use exit(..) when a return value is impossible. For example dividing by zero
> is impossible, so I might say:
>
> divide(A,0) -> exit(you_cant_divide_by_zero);
> divide(A, B) -> A/B.
>
> This *has* to be exit because I cannot return a value.
>
> factorial(N) when N < 0 -> exit(...)
>
> etc. factorial is not defined over negative integers.
>
> When do I user error(...)? - not often. I tend to stick to exit(..) and {ok,...}|{error,...}
>
> Originally (a  long time ago) exit meant "crash with lot of noise and force the programmer
> to re-write their code" - trapping exits was used to close-files etc. and clean up
> after a crash.
>
> /Joe
>
>
>
>        /Richard
>
>     _________________________________________________
>     erlang-questions mailing list
>     erlang-questions@REDACTED <mailto:erlang-questions@REDACTED>
>     http://erlang.org/mailman/__listinfo/erlang-questions <http://erlang.org/mailman/listinfo/erlang-questions>
>
>
>
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions





More information about the erlang-questions mailing list