I find myself writing libraries (like xmerlrpc for XML-RPC). The rule of "just let it die" doesn't apply too much in such code.
You typically don't want to decide to die in library code. You want to postpone the decision until the actual application/service is written.
It's easy to convert error reported by returned value to error reported by exception: just cause badmatch with guard. But to convert an exception to a value is more troublesome. You need to use try..catch.
To properly catch errors in library, one could either use global try..catch hidden in the library code or be much more precise on errors and carefully intercept all the errors that could happen. The latter approach gives an opportunity to give very specific error messages and allows hypothetical bugs in code used by the library to bubble up instead of being disguised as "invalid argument".
As the article says, there are cases when rule of a thumb needs to be broken. Writing a library is such case.
The idiomatic erlang way to deal with such problems is to generate an exception so that the caller can deal with the problem at the next level up that is set up to handle trouble. This could be the level immediately above the library, but conceivably it is much higher up, or the (erlang)process may in fact terminate due to an uncaught exception.
The decision to bail or try to recover should be made at the lowest level capable of making that decision and libraries are simply not empowered to make that decision. You also don't want to force people to catch exceptions around every call to every function in the library.
Is it? A lot of the library code I've seen in Erlang (especially in the standard library) is to avoid exceptions, and instead return either {ok, Val}, or {error, Reason}.
Edit: To clarify tone, I actually would like to know, because I've run into this exact dilemma before. Per the original poster, it seems bad form to throw an exception that has to be handled somewhere in the calling process if I want to be able to send that data to another process. That is, process A makes a library call, cares nothing about the return, just wants to pass it to process B. If it's an error tuple, it can just do that. If it's an exception, it has to explicitly handle it, wrap it in an error tuple, and pass ~that~ along instead, which seems inelegant from library code. It also prevents the library from being able to declare what it returns in the event of a problem via a Dialyzer spec; an error tuple you can fully enumerate what sorts of errors you can return.
Sometimes Erlang standard library code is not the prototypical Erlang development code. For example file_open() is a library function returning an error tuple since it is one of the obvious results file_open() will return.
Now in your code it depends on what you expect or what your guarantees are. If this is a library that expects to open a config file to that is always there, well then a match is better and if it doesn't work an exception is thrown, report written and maybe your process gets restarted.
But now imagine your are writing a configuration file parser. Now you code acts like a library so the input file not being there is a common case and maybe code above needs to decide if it should blow up or not on it.
Anyway that is my amateurish understanding of it. Maybe someone who knows more can chime in and correct me.
You typically don't want to decide to die in library code. You want to postpone the decision until the actual application/service is written.
It's easy to convert error reported by returned value to error reported by exception: just cause badmatch with guard. But to convert an exception to a value is more troublesome. You need to use try..catch.
To properly catch errors in library, one could either use global try..catch hidden in the library code or be much more precise on errors and carefully intercept all the errors that could happen. The latter approach gives an opportunity to give very specific error messages and allows hypothetical bugs in code used by the library to bubble up instead of being disguised as "invalid argument".
As the article says, there are cases when rule of a thumb needs to be broken. Writing a library is such case.