---
A blog post by Eric Lippert, C# guy, sounds about right:
[1]
He classifies exceptions into 4 categories: fatal, boneheaded, vexing and exogenous.
- "Fatal exceptions are not your fault, you cannot prevent them, and you cannot sensibly clean up from them. They almost always happen because the process is deeply diseased and is about to be put out of its misery. Out of memory, thread aborted, and so on. There is absolutely no point in catching these because nothing your puny user code can do will fix the problem. Just let your finally blocks run and hope for the best.". These are like 'panic' in some other languages.
- "Boneheaded exceptions are your own darn fault, you could have prevented them and therefore they are bugs in your code. You should not catch them; doing so is hiding a bug in your code. Rather, you should write your code so that the exception cannot possibly happen in the first place, and therefore does not need to be caught. That argument is null, that typecast is bad, that index is out of range, you’re trying to divide by zero". (i dunno about 'don't need to be caught' in user code though).
- "Vexing exceptions are thrown in a completely non-exceptional circumstance" eg Int32.Parse, "which throws if you give it a string that cannot be parsed as an integer. But the 99% use case for this method is transforming strings input by the user, which could be any old thing, and therefore it is in no way exceptional for the parse to fail". Don't write this sort of thing in libraries; instead, write stuff like TryParse?, which returns both a result and a result code (and so returns a failing result code instead of an exception)
- "exogenous exceptions appear to be somewhat like vexing exceptions" except that they are the result of "untidy external realities" and can't be removed; eg if you call OpenFile? it might throw FileNotFoundException? (you can't fix this by checking if the file exists because it might be deleted in between the call to check if it exists, and the call to OpenFile?). You gotta catch these.
For us, i think:
- fatal exceptions are 'panics'. I think 'panics' is just a certain subclass of exception (maybe Error). Boneheaded exceptions are similar to fatal ones; they are unanticipated so if they occur then the program is known to contain an error and possibly to be in an illegal state
- With our ' operator we can convert vexing exceptions to Maybes (or rather, Results, which are like Maybes except that the None can contain an Exception), so you might think it would be fine for our libraries to have these? But perhaps the default should be to not have them, since having the caller handle a Maybe is tidier than having lots of unhandled exceptions being thrown (because in the latter case, in order to be correct, the code must think about whether invariants would be maintained if the exception was thrown on each possible line, since unhandled exceptions interrupt the code in the middle and cause a possibly non-local return).
- exogenous exceptions should also give Results
---