[erlang-questions] erlang:raise/3 considered harmful?

zxq9 <>
Sat May 14 14:27:36 CEST 2016


On 2016年5月14日 土曜日 13:48:20 Per Hedeland wrote:
> Hi,
> 
> I happened to want something like erlang:raise/3 for a library function
> - I didn't think it existed:-), but found that it does, although it
> comes with a semi-dire warning. The loop/3 function below does exactly
> what I want, specifically: if the fun provided by the caller of
> interate/3 crashes, the caller gets the same exception as if there had
> been no try ... catch, can handle it with hir own try/catch or not, but
> in any case receives full information about *what* went wrong in hir fun
> - all while the "protocol" spoken over the socket remains in sync.
> 
> So, to take heed of the warning - is there a way to write an equivalent
> function *without* using raise/3 - or should it just be considered a
> case of "you really know what you are doing"? I believe I am of
> course:-), but I also think that the code below is a perfectly
> reasonable implementation of a side-effecty library function, and has no
> more to do with debugging or knowing what you're doing than any other
> code...

Two things:

1- Exceptions do indeed suck -- there is usually a better way to deal
   with errors in almost every case. Once you start using them there is
   often a strong urge to accidentally start writing imperative Erlang,
   and that gets so ridiculous so quickly that you'll start hating your
   project.
2- In Erlang I tend to not keep lambdas around for very long as labeled
   objects (like keeping them in main loop state as in this example).

The solution?

*Usually* this purpose can be better served by changing this loop into
a primary/callback module pair, where you have passed the callback module
name in instead of a specific function. This can be as small or as large
as you want, and Erlang has a special syntax to help give you warnings
at compile-time by creating behaviors -- if you haven't done this before,
it can be very rewarding. (The other way is to have an initiator call a
function defined in some module and have the module define its own loop --
the example provided does not include enough boilerplate/"system"-handling
type code to discourage me from writing a custom module to do whatever Fun
is doing there.)

This principle is the whole basis for much of OTP, actually, and is a
structure you will almost certainly wind up re-inventing yourself given
enough time (I've re-invented OTP without realizing it at least 5 times
in different languages and environments... before I realized what was
happening.)

If you have some specific reason a primary/callbacks structure can't work
please detail it and let's see if it can be either worked around cleanly,
or if some other approach is really required.

-Craig


More information about the erlang-questions mailing list