From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,820de86ed0dafb8a X-Google-Attributes: gid103376,public From: Robert A Duff Subject: Re: Help Me Please :) Date: 2000/03/27 Message-ID: #1/1 X-Deja-AN: 603177297 Sender: bobduff@world.std.com (Robert A Duff) References: <89rlvr$gn9$1@nntp3.atl.mindspring.net> <38D8A607.F61F0FFF@mail.com> Organization: The World Public Access UNIX, Brookline, MA Newsgroups: comp.lang.ada Date: 2000-03-27T00:00:00+00:00 List-Id: Mats Weber writes: > Robert A Duff wrote: > > > > Richard D Riehle writes: > > > > > In some languages, exceptions are first class objects. Ada exceptions are > > > not first class objects for very good reasons. > > ^^^^^^^^^^^^^^^^^ > > > > I beg to differ. I think this is one of the few cases where those other > > languages got it right, and Ada got it wrong. > > I think the designers of Modula-3 got it just right. You can have a look > at http://www.m3.org/ I beg to differ, again. ;-) I see several problems with Modula-3's exception mechanism, some of which are shared by Ada. (My knowledge of the language comes from Harbison's book, "Modula-3". I've never written a Modula-3 program.) There's no hierarchy of exceptions. This means that the designer of some code that raises exceptions must decide on the granularity of exception handling; it would be better for the handler to make that decision. For example, one handler might want to handle all "I/O errors", whereas another handler might want to handle just "disk-full error". Making exceptions first-class objects (which they are not, in Ada and Modula-3) would solve this problem, at no cost in language complexity. An exception takes just one parameter. Why not two or three or however many I like? Again, making exceptions extensible object types would solve the problem. The behavior in the presense of "checked run-time errors" (things like divide by zero, arithmetic overflow, array index out of bounds) is not defined by the language. So an array index out of bounds might raise Array_Index_Error on one implementation, and Constraint_Error on another implementation, and simply stop the program dead in its tracks on a third implementation. I don't like that non-portability. (On the other hand, Ada *pretends* that it's OK to raise and handle Constraint_Error, but if you read RM-11.6, you'll find that's not quite true -- and I doubt if any Ada programmer other than Tucker Taft actually *understands* 11.6. So in practise, 11.6 says, "Do not handle predefined exceptions.") The "raises set" of a procedure defines what exceptions it can raise. The problem is that this rule is checked at run time. Java is closer to the right solution -- it checks that rule at compile time. However, Java suffers from the "cry wolf" problem. I think it's possible to avoid the "cry wolf" problem, and still do most of that checking at compile time. The parameter of an exception occurrence (in Ada terms) is a variable. Why not a constant? There is no re-raise statement (spelled "raise;" in Ada), so a "when others" handler (Ada spelling again) can't propagate the same exception. You can't raise the same exception occurrence, because the thing available in the handler is not the occurrence, but just its parameter, and then only if you named a particular exception. Return and exit statements are defined in terms of raising a RETURN or EXIT exception. That seems kludgy to me, because exceptions are for cases where the target of the jump is determined dynamically, whereas return and exit are jumping to a statically-known place. So it's sort of overkill. In practical terms, it means that a "when others" will handle a RETURN or EXIT, and you can't re-raise it, so the return doesn't actually return, and the exit doesn't actually exit the loop. All exceptions must be declared at top level. This solves the kludginess of Ada, where they can be declared anywhere, but act *as if* they were declared at top level. But I think there are better solutions to that problem, based on the "procedure declares what exceptions it can raise" idea of Modula-3, Java, etc. There's nothing like Eiffel's preconditions, postconditions, and invariants, which tie exceptions to the conditions that cause them. In Modula-3, you can say "this thing might raise Stack_Full", whereas in Eiffel you can say, "this thing will raise Stack_Full if Full(S) is True." So, I think CLOS, Clu, and Eiffel (and to some small extent, C++) all have better ideas about exceptions than Modula-3 (or Ada). - Bob