17
$\begingroup$

I'm familiar with a dozen of programming languages which have exceptions in some way, yet I came to witness two "pathological" tendencies.

  1. There doesn't seem to be a common pattern or hierarchy of exceptions. Every language basically rolls its own version, and if the exceptions make it into the standard, then the kinds of exceptions that one finds in the standard would be rather arbitrary (mostly those which were implemented while creating language tools, such as reading source code from string or an exception to invoke debugger, or the one which happens when the file cannot be found etc.)

  2. Exceptions defined by the language are very rarely reused by user programs. There would be usually one or two popular exceptions ("not implement" for example). Though most times programmers will create their own exceptions. (Compare this to, for example, creating new numeric types or new collection types).

This looks like a terrible omission to me. How comes no one knows what kinds of errors will be needed in user programs? I was hoping for there to be a kind of nice hierarchy, similar to numeric types, collections, object system etc.

Worse yet, Goolge and Wikipedia provide very little help on the subject. So far I've only found a paper on functional exception which opens in a passage:

This paper argues that lazy functional programming not only makes built-in exception handling mechanism unnecessary, but provides a powerful tool for developing and transforming programs that use exceptions

(A Functional Theory of Exceptions, Mike Spivey, 1988)

But I think that exceptions are good. I don't want to transform programs that use exceptions, on the contrary, I want to make the use of exceptions less chaotic.

The question:

Is there a theory of exceptions? If so, what is it called? What are, if any, the cornerstone works outlining the basis of it?

$\endgroup$
  • $\begingroup$ exceptions are a rather new invention, maybe less than ~20yr old, arising somewhat out of C's "longjmp". they are mostly connected to OOP. it seems an ideal usage/theory/best practices are still under evolution. java has one of the more elaborate models. there are many "antipatterns" relating to exceptions as you note. some of this is connected to the theory of "fault tolerant computing" which also seems somewhat in its infancy overall. $\endgroup$ – vzn Oct 15 '13 at 3:17
  • $\begingroup$ You could consider exceptions a subset of continuation theory. See en.wikipedia.org/wiki/Continuation $\endgroup$ – jmite Oct 15 '13 at 3:35
  • $\begingroup$ @jmite Exceptions and continuations are very different. Exceptions bind dynamically to their handlers, while continuations do so statically. In general, continuations on their own cannot be used to implement exceptions, at least in the presence of types, see e.g. Typed Exceptions and Continuations Cannot Macro-Express Each Other. $\endgroup$ – Martin Berger Oct 15 '13 at 11:41
  • $\begingroup$ "Exceptions defined by the language are very rarely reused by user programs." This is so true! Defining custom exceptions is very rarely needed. For example python and its stdlib define something like 160 exceptions. The chances that the exception you are thinking about wasn't defined there is very small. Some(most?) of these exceptions are not widely know. For example the LookupError would perfectly fine for every custom container, but I lot of people do not even know it exists. $\endgroup$ – Bakuriu Oct 15 '13 at 19:25
  • 1
    $\begingroup$ @jmite One more encounter I had with exceptions before this topic was from Benjamin C. Pierce's book Types and Programming Languages. Where he mentions errors in the context of defining a type of a function. I.e. from his standpoint, errors are just yet another values returned from functions (and together with the other argument they form a whole type, if I'm allowed to say so). $\endgroup$ – wvxvw Oct 15 '13 at 23:38
8
$\begingroup$

There's a large number of publications on exceptions, with quite a few theoretical investigations. Here is an unstructured and far from complete list with some examples. Sorry, I don't have time at the moment for a more focussed reply.

  • B. Randell, System Structure for Software Fault Tolerance.
  • J. B. Goodenough. Exception handling: Issues and a proposed notation.
  • J. B. Goodenough. Structured exception handling.
  • B. G. Ryder, M. L. Soffa, Influences on the Design of Exception Handling.
  • D. Teller, A. Spiwack, T. Varoquaux, Catch me if you can: Towards type-safe, hierarchical, lightweight, polymorphic and efficient error management in OCaml.
  • X. Leroy, F. Pessaux, Type-based analysis of uncaught exceptions.
  • R. Miller, A. Tripathi, Issues with Exception Handling in Object-Oriented Systems.
  • S. Drew, K. J. Gough, J. Ledermann, Implementing Zero-Overhead Exception Handling.
  • B. Stroustrup, Exception Safety: Concepts and Techniques.
  • D. Malayeri, J. Aldrich, Practical Exception Specifications.
  • H. Nakano, A Constructive Formalization of the Catch and Throw Mechanism.
  • A. Nanevski, A Modal Calculus for Exception Handling.
  • P. de Groote, A Simple Calculus of Exception Handling.
  • H. Thielecke, On Exceptions and Continuations in Presence of State.
  • J. G. Riecke, H. Thielecke, Typed Exceptions and Continuations Cannot Macro-Express Each Other.
  • M. van Dooren, E. Steegmans, Combining the Robustness of Checked Exceptions with the Flexibility of Unchecked Exceptions using Anchored Exception Declarations.
  • J. A. Vaughan, A logical interpretation of Java-style exceptions.
  • S. Marlow, S. Peyton Jones, A. Moran, Asynchronous Exceptions in Haskell.
  • B. Jacobs, F. Piessens, Failboxes: Provably Safe Exception Handling.
$\endgroup$
  • $\begingroup$ Wow, thanks a lot! Will take me few months (if not more) to get back with the positive reply :) Now I'm torn between few books not knowing where to start! $\endgroup$ – wvxvw Oct 15 '13 at 16:14
  • 2
    $\begingroup$ A lot of these papers are about implementing or modeling exceptions in programming languages, and not how to design an exception hierarchies. Could you trim the list down to the relevant papers? $\endgroup$ – Gilles Oct 15 '13 at 22:14
  • $\begingroup$ @Gilles The original question was a bit unclear. I reckon that what counts as appropriate exceptions depends mostly on the application. The only real theoretical problem with exceptions is the tradeoff between (1) coupling unrelated modules through exceptions (this is why no language after Java has mandatory exception specifications), (2) giving the user of a module some indication what kinds of erros to expect, and (3) compiler help with error handling. As far as I can see, no really convincing solution to this conundrum has been found yet. $\endgroup$ – Martin Berger Oct 16 '13 at 10:43
6
$\begingroup$

I don't know whether or not there is a theory, but there may be an emerging pragmatic experimental science.

The best source I can think of is Bjarne Stroustrup, The Design and Evolution of C++, Addison-Wesley, 1994. If I remember correctly (it's a very good book and people keep borrowing it from me and not returning it, so I don't have a copy at the moment) there's a chapter about exceptions. The C++ committee under Stroustrup required a lot of empirical evidence that a proposed feature was necessary before they were willing to add it to the language definition. The Wikipedia page about exceptions has the following quote from that book:

At the Palo Alto [C++ standardization] meeting in November 1991, we heard a brilliant summary of the arguments for termination semantics backed with both personal experience and data from Jim Mitchell (from Sun, formerly from Xerox PARC). Jim had used exception handling in half a dozen languages over a period of 20 years and was an early proponent of resumption semantics as one of the main designers and implementers of Xerox's Cedar/Mesa system. His message was termination is preferred over resumption; this is not a matter of opinion but a matter of years of experience. Resumption is seductive, but not valid. He backed this statement with experience from several operating systems. The key example was Cedar/Mesa: It was written by people who liked and used resumption, but after ten years of use, there was only one use of resumption left in the half million line system -- and that was a context inquiry. Because resumption wasn't actually necessary for such a context inquiry, they removed it and found a significant speed increase in that part of the system. In each and every case where resumption had been used it had -- over the ten years -- become a problem and a more appropriate design had replaced it. Basically, every use of resumption had represented a failure to keep separate levels of abstraction disjoint.

In C++ the real win is RAII, which makes it much easier to handle resource deallocation during errors. (It doesn't do away with the need for throw and try-catch, but it means you don't need finally.)

I think the thing that convinced them they needed exceptions is generic containers: the container writer knows nothing about the kinds of errors that the contained objects might need to return (much less how to handle them), but the code that inserted those objects into the container must know something about what those objects' interface is. But since we know nothing about what kinds of errors the contained objects can throw, we can't standardize on exception types. (Contrapositively: if we could standardize exception types then we wouldn't need exceptions.)

The other thing that people seem to have learned over the years is that exception specifications are hard to put into a language correctly. See for example this: http://www.gotw.ca/publications/mill22.htm, or this: http://www.gotw.ca/gotw/082.htm. (And it's not just C++, Java programmers also have lengthy arguments about their experiences with checked versus unchecked exceptions.)

A little on the history of exceptions. The classic paper is: John B. Goodenough:"Exception handling: issues and a proposed notation," Commun. ACM 18(12):683-696, 1975. But exceptions were known before that. Mesa had them in about 1974, and PL/I may have had them too. Ada had an exception mechanism before 1980. I believe that C++'s exceptions were most influenced by the experience with Barbara Liskov's CLU programming language from about 1976. Barbara Liskov: "A history of CLU," in History of programming languages---II, Thomas J. Bergin, Jr. and Richard G. Gibson, Jr. (Eds.). pp. 471-510, ACM, 1996.

$\endgroup$
  • $\begingroup$ This is interesting and I will have to research more to reply better. But as of so far: I know there is a very strong objection to use exceptions in C++ ever (perhaps an anecdote, but iirc Google coding conventions used to forbid the use of exceptions). Java checked exceptions are certainly a unique and thus interesting experiment, but the feature earned so many bad credits over the course of its history... most people simply rethrow them at runtime (although this may be just related to syntax). $\endgroup$ – wvxvw Oct 15 '13 at 7:43
  • $\begingroup$ I'm more familiar with Common Lisp classification of exceptions, where they tried to (although with little success) split them according to the level of threat they pose to program. e.g. serious-condition vs simple-condition. I'm also now reading J. L. Austing, where he classifies errors (unrelated to programming) into groups based on how the system failed to perform the task (eg. improper parts used vs insincere intentions). Which is not immediately applicable to programming, but might be after some refinement. $\endgroup$ – wvxvw Oct 15 '13 at 7:48
  • $\begingroup$ @Wandering Logic I have upvoded because you have explained why C++ excpetios are sux and that educated inclusion of features might destroy the language. $\endgroup$ – Val Oct 15 '13 at 7:55
  • $\begingroup$ @wvxvw The very strong objection against exceptions in C++ comes from two facts: there is no finally construct and nobody else uses exceptions. The first problem also aggravates the second. That is, When you have no finally, you cannot close the resource when exception happens. Because nobody uses exceptions, all functions/APIs avoid them, you must invest a lot rebuilding the whole traditional C++ infrastructure wrapping all functions with your exceptions to start getting benefits from them in your code. But lack of finally makes this approach impossible also. $\endgroup$ – Val Oct 15 '13 at 8:05
  • $\begingroup$ @wvxvw: Google's conventions ban throwing exceptions across module (.so) boundaries. This is because exceptions in C++ use run-time type information (RTTI), and Linux didn't do a good job of implementing run-time typing. In Linux you can only pass run-time types reliably between modules if you compiled the modules with the same version of the same compiler and linked against the identical version of libstdc++. Really this is a rejection of C++ in general by the Linux community, not a rejection of exceptions specifically. $\endgroup$ – Wandering Logic Oct 15 '13 at 11:19
3
$\begingroup$

Let me just point out that exceptions are a case of computational effect. Other computational effects are mutable state, I/O, non-determinism, continuations, and many others. So your question could be asked more generally: how do we form hierarchies of computational effects, how do we organize them, and why do we have the ones we have, and not others, etc.

$\endgroup$
  • 1
    $\begingroup$ I think this is completely irrelevant. The question isn't about modeling the notion of exceptions, but about mapping it to errors — I think the right way to describe it from a PLT perspective would be a theory of exception hierarchies. $\endgroup$ – Gilles Oct 15 '13 at 22:16
  • $\begingroup$ Hmm, you're right. I fixed the answer to point this out, but I think there's no need to delete it. What do you think? $\endgroup$ – Andrej Bauer Oct 16 '13 at 10:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.