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.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,1592759aa83d0d45 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2003-05-28 15:13:37 PST Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!news.uchicago.edu!newsswitch.lcs.mit.edu!nntp.TheWorld.com!not-for-mail From: Robert A Duff Newsgroups: comp.lang.ada Subject: Re: Suggestion for Ada 200x - Interface inheritance Date: 28 May 2003 18:13:35 -0400 Organization: The World Public Access UNIX, Brookline, MA Message-ID: References: <0Pxza.699607$OV.652508@rwcrnsc54> <5ad0dd8a.0305240435.337d9373@posting.google.com> <5ad0dd8a.0305250612.ec54c23@posting.google.com> <3ED1039F.7010001@spam.com> <719Aa.14547$fT5.3595@nwrdny01.gnilink.net> NNTP-Posting-Host: shell01.theworld.com Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: pcls4.std.com 1054160015 21180 199.172.62.241 (28 May 2003 22:13:35 GMT) X-Complaints-To: abuse@TheWorld.com NNTP-Posting-Date: Wed, 28 May 2003 22:13:35 +0000 (UTC) User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.2 Xref: archiver1.google.com comp.lang.ada:37951 Date: 2003-05-28T18:13:35-04:00 List-Id: Hyman Rosen writes: > Wesley Groleau wrote: > > But that meant adding a throws clause to each of hundreds of files. > > 'Throws' clauses are a really bad idea, the more so because it seems > so right on first appraisal. Throws clauses are a bad idea in Java, because they require scattering a whole lot of useless exception handlers all over the place. Or else a whole lot of useless throws clauses. But I don't think they're a fundamentally bad idea; I think it would be possible to design a language without those problems. One thing Java got right is that there are two kinds of exceptions: For one kind, you want to declare "this procedure can raise X", and force callers to either handle it or declare that they throw it. For the other kind, you don't want to declare anything. One thing Java got wrong is the some of the exceptions are in the wrong category. For example, all the streams operations can throw I/O exceptions, even though streams are not necessarily tied to I/O. If an open-file operation is designed to raise a file-not-found exception, then I think it's reasonable to require the caller to handle it (or reraise it). But a read-from-stream operation should not require any extra mumbo-jumbo at the call site; it might not even be reading from a file. I also think you should let the programmer decide which exceptions are in which category. For example, an out-of-memory exception (Storage_Error, in Ada) should, by default, not require any declarations, since pretty-much anything can raise it. But in an embedded system, you might want the compiler to prove that out-of-memory can't happen. I envision a compiler that calculates (at link time) a worst-case stack size for every procedure (including called procedures). The programmer could say, "on entry to this procedure, make sure there's enough stack space". If the procedure is recursive, or declares something like: X: String(1..N); where N is not known, the "worst case" would be "the size of the whole address space". But if you don't do those things, the "worst case" could be reasonable, and the compiler could prove at compile time (link time, really) that certain regions of code (perhaps the whole program) do not run out of stack space. Consider also something like a generic iterator: generic with procedure Action(X: Element); procedure Set_Iterate(S: Set); -- Calls Action once for each element of the Set. Presumably Set_Iterate can raise whatever exceptions are raised by the actual procedure passed to Action. But you don't want to say Set_Iterate raises "any exception". You want to say, "Set_Iterate raises whatever exceptions are raised by Action". That's not known at compile time of the generic, but it could be known at compile time of the instantiations. So for "throws clauses" to work well, we need some sort of pass-through concept -- "this throws what that throws". This would allow abstraction layers that simply pass exceptions through to avoid saying "throws anything" and the subsequent clutter in clients. Another point is that most exceptions are really preconditions. See Eiffel, and design-by-contract. You want to declare not only that this procedure raises Queue_Empty_Error, but also under what conditions that exception is raised (e.g. if Is_Empty is True), and that Queue_Empty_Error gets raised before modifying the queue. And if you have pre- and postconditions, I think you want to attach postconditions to exceptional situations. You want a way to express, "If this procedure returns normally, then such-and-such is true. If it raises File_Not_Found, then so-and-so is true. And if it raises Storage_Error, all bets are off (i.e., any data touched by this procedure might have been damaged, so don't touch it)." And finally, you want user-settable defaults. Like, "All procedures in this package, and all of its descendants, behave such-and-such a way in the presence of so-and-so exception." - Bob