
W liście z wto, 03-08-2004, godz. 13:05 +0200, Bjoern Knafla napisał:
Herb Sutter gave these rules :
An error is any failure that prevents a function from succeeding. Three main kind of errors: [...]
These kinds don't explain much. They don't give a clue which errors to report by exceptions and which by return values, because they don't distinguish the reasons for which a (pre|post)condition can't be fulfilled. And I see no point in distinguishing potential errors on this axis. I divide exceptional situations into 4 groups: 1. Expected error: The result can't be computed from this data; the caller was not supposed to check this beforehand because it would duplicate work of the function, or there would be a race condition, or the design is simpler that way. 2. Program error: The given function was not supposed to be invoked in this way by other parts of the program (with these arguments, or with this external state, in this order wrt. other functions etc.). 3. Out of resource: The function is sorry that it was not able to produce the result due to limited memory or arithmetic precision or similar resources. "Not yet supported" is also in this group. 4. Impossible error: The function thought this couldn't happen, it must have a bug. This is like 2 in that there is a bug somewhere, but like 1 in that the calling code is probably fine. I/O errors can be expected errors or out of resource conditions, depending on whether they were caused by bad input or by external failure. Group 1 should be reported in Haskell by a distinguished result (Maybe, Either, custom type) or by an exception passed in a suitable monad (well, Maybe is a monad; this could be even the IO monad). Other groups are handled in a similar way. In Haskell they can be reported by a bottom, e.g. 'error' function. It makes sense to catch them on a toplevel of the program or a large unit, and it's good that GHC provides a way to catch them. There may be other actions possible than just aborting the program: report the problem to the user, abort just the given operation, but try to continue other work; save user data before aborting; log the error or report it in an appropriate channel, e.g. output a HTML page in case of a CGI program. Sometimes the same function makes sense in two variants: one which reports an expected error, and another which treats it as a program error. Example: lookup in a dictionary. Sometimes the qualification of an error changes while it is propagated. I haven't thought about all cases, but for example program errors become impossible errors if the caller thought that the arguments it passed were good, and expected errors become program errors if the caller's caller was not supposed to give arguments which cause such problems. The most important distinction is between expected errors, whose way of reporting should be visible in the interface and which should be checked for in the calling code, and program errors, which should be automatically propagated and reported near the toplevel. -- __("< Marcin Kowalczyk \__/ qrczak@knm.org.pl ^^ http://qrnik.knm.org.pl/~qrczak/