Path: utzoo!attcan!uunet!brunix!drc From: drc@cs.brown.edu (David R. Chase) Newsgroups: comp.lang.modula2 Subject: Re: Exceptions (was Type extension, Oberon) Message-ID: <35384@brunix.UUCP> Date: 6 Apr 90 21:21:41 GMT References: <9004061748.AA07286@ctc.contel.com> Sender: news@brunix.UUCP Reply-To: drc@cs.brown.edu (David R. Chase) Organization: Guest of Brown University Department of Computer Science Lines: 63 Real-location: Menlo Park, CA I tend to the pro-exception camp, with reservations. I've written and debugged bits and pieces of Modula-3, and written a back-end for a M-3 compiler. The 15-line-normal/50-line-exceptional example notwithstanding, I have found exceptions to be useful, and I find them useful because of the way they allow separation of "normal" from "not normal" cases. In some numerical code that I wrote, it was quite handy to take care of "failed to converge" and "divide-by-zero" as exceptional cases. Exceptions also have one useful abuse -- locally, they do a good job as "structured goto", and a compiler can easily turn that into a goto and avoid the overhead of exception dispatch. Exceptions are somewhat better than return codes for construction of reliable programs, because (Modula-3 semantics) if your code fails to catch a raised exception, then it blows up ("Uncaught exception -- core dumped"). This doesn't solve the whole problem -- testing/verification of code may still fail to ever raise an exception that won't be caught -- but it's a lot better than nothing. Plus, in Modula-3 procedure signatures include declarations of what exceptions will be raised -- a compiler can (and one does/did) warn of places where an uncaught exception may occur. Now, the reservations. There are holes in this, of course -- the default signature for Modula-3 procedures is "RAISES ANY", which means that a sloppy programmer will get little help from the compiler. This was hotly debated among the Modula-3 committee, and at least one paper was produced arguing for a default of RAISES NONE. Furthermore, a TRY-EXCEPT-ELSE-END will catch everything, which may be a bit of overkill. There's stylistic problems too; at least one person has argued that the default exception list for extensible packages ought to be "RAISES ANY" because "who knows what exceptions will be appropriate to the extensions?" and I don't really have a good counter-argument. Some future descendant of the language might steal a bit from the C++ proposals, and either allow some sort of "subtyping" of exceptions, or go so far as to say that exceptions are just objects (i.e., a declaration of what exceptions might be raised = a declaration of the possible types that might be exceptionally returned). This gives some additional flexibility that might help avoid the use of RAISES ANY. (DON'T look for this in anything called Modula-3; I'm not on the committee, but I'm pretty sure of their behavior in this case.) My biggest gripe concerning exceptions has nothing to do with their typical use or language semantics. It turns out that it is difficult to *generate* efficient, reliable object code using either C as an intermediate language or a C-based backend. People from Xerox say that it isn't too bad if you just wrap each guarded block into its own nested procedure (simulated, of course, in C, with a great number of pointers), but I don't have a great deal of confidence in that (i.e., I'd like to see a detailed and thorough comparison). Setjmp+longjmp, of course, is a flaky option, since that combination rarely combines correct semantics and speed, and often possesses neither. It's "just a SMOP" of build an optimizing backend safe for Modula-3-style exceptions, but it hasn't happened yet. The Acorn Modula-2+ compiler generated quite acceptable code without any significant optimizations, however, so maybe this isn't that large a problem. Do note that their M2+ compiler had its own back-end -- it just did a good job of generating code. David