!standard 4.4(3/3) 12-06-28 AI12-0022-1/03 !standard 11.2(6) !standard 11.3(2/2) !standard 11.3(3) !standard 11.3(3.1/2) !standard 11.3(4/2) !standard 11.4.1(10.1/3) !class Amendment 12-03-16 !status ARG Approved 9-0-0 12-06-1 !status work item 12-02-24 !status received 12-02-24 !priority High !difficulty Medium !subject Raise expressions for specifying the exception raised for an assertion !summary The raise_expression is added to Ada. !problem We want to encourage the conversion of comments to predicates/preconditions in existing libraries. However, changing the exception raised may be an unacceptable incompatibility. Some mechanism should be provided to allow specifying the exception to be raised by the failure of an assertion. !proposal (See summary.) !wording Add to 4.4(3/3): | raise_expression Rename 11.3 to "Raise Statements and Raise Expressions" Add before 11.2(6): An *exception*_name of an exception_choice shall denote an exception. Add after 11.3(2/2) [Syntax] raise_expression ::= raise *exception*_name [with *string*_expression] Modify 11.3(3): [Legality Rules] {An exception_name of}[The name, if any, in] a raise_statement {or raise_expression} shall denote an exception. A raise_statement with no exception_name (that is, a re-raise statement) shall be within a handler, but not within a body enclosed by that handler. Modify 11.3(3.1/2): [Name Resolution Rules] {A *string*_expression of}[The expression, if any, in] a raise_statement {or raise_expression}[,] is expected to be of type String. Add after 11.3(3.1/2): A raise_expression is expected to be of any type. [This is the same wording as type conversions, see 4.6(6) - Editor.] Modify 11.3(4/2): [Dynamic Semantics] ... For the execution of a raise_statement with an exception_name, the named exception is raised. {Similarly, for the evaluation of a raise_expression, the named exception is raised.} [{In both of these cases, if}[If] a string_expression is present, the expression is evaluated and its value is associated with the exception occurrence.] ... Modify 11.4.1(10.1/3): ... For the occurrence raised by a raise_statement {or raise_expression} with an exception_name and a string_expression, the message is the string_expression. For the occurrence raised by a raise_statement {or raise_expression} with an exception_name but without a string_expression, the message is a string giving implementation-defined information about the exception occurrence. ... !discussion The intent is that the semantics of a raise_expression is the same as calling a function of the form: function returns is begin raise exception_name [with string_expression]; return X:; -- Junk return required by Ada 83 through at least 2012 end ; --- A raise_expression has the precedence of a relation. This means that it will need to be parenthesized in most contexts. But it will not need to be parenthesized when used directly in a context like a conditional expression or return statement. It also will not need to be parenthesized when used directly with a logical operator/operation (and, and then, etc.). For instance: (if Mode /= In_File then raise Mode_Error) is preferable to: (if Mode /= In_File then (raise Mode_Error)) We can't allow a raise_expression to go unparenthesized in all contexts, as there is an ambiguity with the optional string_expression. Does raise Some_Error with "aaa" & "bbb" mean (raise Some_Error with "aaa") & "bbb" or (raise Some_Error with "aaa" & "bbb") We avoid this situation by using precedence so that the raise_expression has to be surrounded by parentheses if used with the "&" operator. --- A raise_expression resolves to "any type". That means it might be necessary to qualify it in some circumstances, but the need for that should be rare. It was suggested that the type be "any Boolean type", but that limits the usefulness of the construct in conditional expressions. For instance, imagine the following expression function: function Foo (Bar : in Natural) return Natural is (case Bar is when 1 => 10, when 2 => 20, when others => (raise Program_Error))); This is allowed as a raise_expression resolves to "any type"; if it resolved to "any Boolean type", some junk expression like "and True" would have to appended to make it legal -- which would do nothing for readability or understandability. In addition, resolving to "any type" also solves the problem posed in AI12-0029-1, as that means "return raise Not_Implemented_Error;" is legal for any function. This makes it an easy idiom to use for functions that (temporarily) always raise an exception. --- Example: Imagine the following routine in a GUI library: procedure Show_Window (Window : in out Root_Window); -- Shows the window. -- Raises Not_Valid_Error if Window is not valid. We would like to be able to use a predicate to check the comment. With the "raise_expression" we can do this without changing the semantics: subtype Valid_Root_Window is Root_Window with Dynamic_Predicate => Is_Valid (Valid_Root_Window) or else raise Not_Valid_Error; procedure Show_Window (Window : in out Valid_Root_Window); -- Shows the window. If we didn't include the raise_expression here, using the predicate would change the exception raised on this failure. That could cause the exception to fall into a different handler than currently, which is likely to not be acceptable. An alternative way to write the predicate might be preferable: subtype Valid_Root_Window is Root_Window with Dynamic_Predicate => (if not Is_Valid (Valid_Root_Window) then raise Not_Valid_Error); Similarly, the various Containers packages in Ada could use predicates or preconditions in this way to make some of the needed checks; but that can only be done if the semantics remains unchanged (raising Program_Error and Constraint_Error, not Assertion_Error). (The !proposal also shows how this could be used in Text_IO and other I/O packages.) --- We considered a number of other alternatives to fix this problem: Alternative #1: There is an optional "exception" clause on predicates and preconditions. This specifies the exception that will be raised on the failure of the check. Alternative #2: There is an aspect "Pre_Exception" that specifies the exception to raise for Pre, and similarly for other assertions. Alternative #3: Do nothing. The user can write a function that works like the proposed raise expressions: function Raise_Mode_Error (For_File : File_Type) return Boolean is begin raise Mode_Error with Name (For_File); return False; -- At least one return is required (see AI12-0029-1). end Raise_Mode_Error; The problem with both of the first two alternatives is that the interface of a subprogram may include multiple exceptions that need to be checked: procedure Put (File : in File_Type; Str : in String) with Pre => (Is_Open(File) or else raise Status_Error) and then (Mode(File) = Out_File or else raise Mode_Error with "Cannot read " & Name(File)); This cannot be handled with a single exception clause or aspect. This particular problem could be addressed by making the Status_Error check into a predicate, but that isn't likely to always work. Another way to address the problem using an exception clause or aspect would be to allow multiple Pre aspects on a single declaration: procedure Put (File : in File_Type; Str : in String) with Pre => Is_Open(File), Pre_Exception => Status_Error, Pre => Mode(File) = Out_File, Pre_Exception => Mode_Error; but notice that the order of declaration of the preconditions is significant here, which is likely to be confusing (and a significant change from the current rules, where the order of evaluation of preconditions is unspecified). In addition, we've lost the exception message that gives the name of the file with the wrong mode. That's a loss; we could introduce another aspect to deal with that, but by now it's clear that this solution is not "simpler" by any stretch of imagination. The problem with the last alternative is the need to clutter the program with a number of exception raising functions. This is especially problematic in existing packages (like the language-defined ones) where adding these routines may not be allowed. Thus the selected alternative seems clearly to be the best option. !ACATS test ACATS B and C-Tests would be needed for raise_expression. !appendix This AI was split from AI05-0290-1; during meeting #46 there was general agreement that this is an important issue but the solution looked more complex than a last-minute fix would allow. **************************************************************** [The following splits from a thread about and filed in AI05-0290-1; it's more relevant here - Editor.] From: Tucker Taft Sent: Tuesday, March 6, 2012 4:56 PM > ... > To use preconditions or predicates in Text_IO, for ex, one needs a way > to specify which exception gets raised (as you suggested at the Kemah > meeting). I strongly agree that's a good idea, and I strongly believe > it's too late to add that feature to Ada 2012 now. Geert had an interesting suggestion of writing a precondition as: procedure Read(File : File_Type; ...) with Pre => Is_Open(File) or else Raise_Status_Error;" This seems like a neat way to get the right exception raised, at least for a precondition. For what that's worth. **************************************************************** From: Erhard Ploedereder Sent: Wednesday, March 7, 2012 5:33 PM > Geert had an interesting suggestion of writing a precondition as: > > procedure Read(File : File_Type; ...) > with Pre => Is_Open(File) or else Raise_Status_Error;" If the decision goes the way it seems to go, please make sure to put this in the discussion in lieu of Randy's subtype predicate example with the same functionality that is currently there. In Houston, I blindly copied it; I should already have turned it into a PRE example. I'd go as far as to ratify this change even at such a late date! It is such an obvious and major improvement without hidden traps. **************************************************************** From: Randy Brukardt Sent: Thursday, March 8, 2012 1:08 AM I think you missed the point (I did, too, until you repeated it) -- there is no change here! Geert is defining a function Raise_Status_Error as: function Raise_Status_Error return Boolean is begin raise Status_Error; return False; -- To meet the requirement of a return statement. end Raise_Status_Error; And then using it in the Pre expression as Tucker noted. In that case, either the "real" precondition works, or the "or else" is executed, which raises the "right" exception. We never get the chance to raise Assertion_Error. It's still a work-around (you have to define a bunch of these rather silly Raise_ functions), but it appears to work for both predicates and preconditions. (Presuming that raising an exception is not considered a "side-effect", and I don't think it can be.) It definitely reduces the urgency to get the exceptions right. Something for John's book (and the Rationale, too?). I originally read this as: procedure Read(File : File_Type; ...) with Pre => Is_Open(File) or else raise Status_Error;" which is the sort of syntax change that people wanted to think about some more in Kemah, and I don't think anything has changed there. But Geert's trick doesn't require any changes at all. P.S. I'm still bummed that the roller coaster in Kemah was broken the whole time I was there. It seemed such an appropriate metaphor for the whole standards process (lots of ups and downs!). I'm also fond of the expression "herding cats", but it's nowhere near as much fun to ride... :-) **************************************************************** From: John Barnes Sent: Thursday, March 8, 2012 2:19 AM > It's still a work-around (you have to define a bunch of these rather > silly Raise_ functions), but it appears to work for both predicates > and preconditions. (Presuming that raising an exception is not > considered a "side-effect", and I don't think it can be.) It > definitely reduces the urgency to get the exceptions right. Something > for John's book (and the Rationale, too?). Obviously. John has been glancing at this stuff but is busy with Spark book right now. That section of the rationale is now with the Journal. I wonder if it is too late for a PS at the end? I will copy this to Miguel. **************************************************************** From: Robert Dewar Sent: Thursday, March 8, 2012 6:17 AM > function Raise_Status_Error return Boolean is > begin > raise Status_Error; > return False; -- To meet the requirement of a return statement. > end Raise_Status_Error; (BTW, the requirement for a return statement is silly and infuriating! and quite useless, since you will get a compiler warning anyway if you forget to block a branch with a raise or return. Any compiler that does NOT give this warning is IMO unusable. This silly requirement should be fixed (but it is hard to do since you have to talk about flow), or removed. [Editor's note: AI12-0029-1 discusses this issue and possible solutions.] > And then using it in the Pre expression as Tucker noted. In that > case, either the "real" precondition works, or the "or else" is > executed, which raises the "right" exception. We never get the chance > to raise Assertion_Error. > > It's still a work-around (you have to define a bunch of these rather > silly Raise_ functions), but it appears to work for both predicates > and preconditions. Actually its useful in general for expanding the use of conditional expressions :-) **************************************************************** From: Robert Dewar Sent: Thursday, March 8, 2012 6:19 AM Another form of "Geert's trick" is Constraint_Error'Raise; Not sure if you are allowed to make a new attribute with a reserved name, if not Constraint_Error'Raise_Exception Geert, shall we implement this? **************************************************************** From: Bob Duff Sent: Thursday, March 8, 2012 7:05 AM > Another form of "Geert's trick" is > > Constraint_Error'Raise; > > Not sure if you are allowed to make a new attribute with a reserved > name, It is not. I'm not sure that rule serves any practical purpose; ARG could repeal it in Ada 2020, or even as a binding interp for Ada 2012. >...if not > > Constraint_Error'Raise_Exception > > Geert, shall we implement this? How is this an improvement over: Pre => ... or else Raise_Exception(Constraint_Error'Identity); which I suggested earlier, and you said you didn't like it, but didn't explain why. To me, all of these: Pre => ... or else Raise_Constraint_Error; Pre => ... or else Constraint_Error'Raise_Exception; Pre => ... or else Raise_Exception(Constraint_Error'Identity); are kludges. It would be better to allow (in Ada 2020) "raise ..." as an expression: Pre => ... or else raise Constraint_Error; Pre => ... or else raise Constraint_Error with "some message"; I object to adding kludgy new impl-def attributes, (1) when we already have a kludgy standard attribute that can do the same thing ('Identity), and (2) there's a non-kludgy solution we can use as soon as we decide it belongs in Ada 2020. **************************************************************** From: Robert Dewar Sent: Thursday, March 8, 2012 7:13 AM I suggest: >>> Constraint_Error'Raise_Exception And Bob says: >> How is this an improvement over: >> >> Raise_Exception(Constraint_Error'Identity); Surely even language lawyers are sensitive to verbose crud? :-) :-) I really would like to be able to write Constraint_Error'Raise In fact I am tempted to just implement that anyway. The rule forbidding it serves no purpose IMO. And if I could add syntax, I would not mind raise Constraint_Error; that would be fine :-) **************************************************************** From: Robert Dewar Sent: Thursday, March 8, 2012 7:14 AM >> Not sure if you are allowed to make a new attribute with a reserved >> name, > > It is not. I'm not sure that rule serves any practical purpose; ARG > could repeal it in Ada 2020, or even as a binding interp for Ada 2012. Right, I don't think it helps portability, unlike pragmas, you can't ignore unrecognized attributes. I would be in favor **************************************************************** From: Erhard Ploedereder Sent: Thursday, March 8, 2012 11:46 AM > I think you missed the point (I did, too, until you repeated it) -- > there is no change here! Geert is defining a function Raise_Status_Error as: I did indeed miss this idea. All the more reason to make it part of the language syntax so it reads something like procedure Read(File : File_Type; ...) with Pre => Is_Open(File) or else raise Status_Error; or with no syntactic contortions: procedure Read(File : File_Type; Element: out Elem_Type) with Pre => Is_Open(File), Pre_Exception => Status_Error; with Post => valid(Element), Post_Exception => Read_Error; "All the more reason" = - There is a simple implementation model that compiler vendors can use. - It shows that there are no traps. - One can use the syntax notation in the specification of packages not only for the sake of implementations, but also for the sake of readers, e.g., in a scientific paper, since it is standardized. (This is my most important reason in favor of the feature.) The RM Annexes would be half as complicated to read. I would have severe reservations to standardize the "hack" of using user-provided exception-raising function calls in the predicate). **************************************************************** From: Tuillo Vardanega Sent: Thursday, March 8, 2012 11:57 AM For all it may matter, I begin -- at long last -- to see convergence in the recent flurry of discussion. And I second Erhard's recommendation, the one "free of syntactic contortions". **************************************************************** From: Tucker Taft Sent: Thursday, March 8, 2012 12:09 PM > For all it may matter, I begin -- at long last -- to see convergence > in the recent flurry of discussion. > And I second Erhard's recommendation, the one "free of syntactic > contortions". I think it looks interesting, but for Ada 2020 at this point. **************************************************************** From: Randy Brukardt Sent: Thursday, March 8, 2012 12:11 PM ... > I really would like to be able to write > > Constraint_Error'Raise > > In fact I am tempted to just implement that anyway. > The rule forbidding it serves no purpose IMO. If you can't specify an exception message, the value drops a lot. This "attribute" solution suffers from that problem; I don't see a sensible way to add a message. > And if I could add syntax, I would not mind > > raise Constraint_Error; > > that would be fine > > :-) Right; I have much more sympathy for that. But I think I agree with Bob, that such inventions have to wait for Ada 2020. (Which doesn't mean that we can't design them now and vote to add them at the next meeting.) Joyce tells me that we need to deliver the Standard next week, and this is definitely not the time to add new inventions. That ended at noon on Feb 26th (that is, the end of Kemah meeting). **************************************************************** From: Geert Bosch Sent: Thursday, March 8, 2012 1:10 PM > Another form of "Geert's trick" is > > Constraint_Error'Raise; > > Not sure if you are allowed to make a new attribute with a reserved > name, if not > > Constraint_Error'Raise_Exception > > Geert, shall we implement this? No, I'd really like to avoid any implementation-specific attributes in the preconditions. Then any static analysis tool can reason about behavior without having to refer to specific compiler, or version thereof. Fortunately, it appears that with the current Ada 2012 definition that is entirely possible. **************************************************************** From: Erhard Ploedereder Sent: Thursday, March 8, 2012 2:45 PM > procedure Read(File : File_Type; Element: out Elem_Type) > with Pre => Is_Open(File), Pre_Exception => Status_Error; > with Post => valid(Element), Post_Exception => Read_Error; The above is an interesting suggestion, since we could implement it in any case without needing a language extension. **************************************************************** From: Robert Dewar Sent: Thursday, March 8, 2012 2:47 PM >> For all it may matter, I begin -- at long last -- to see convergence >> in the recent flurry of discussion. >> And I second Erhard's recommendation, the one "free of syntactic >> contortions". > > I think it looks interesting, but for Ada 2020 at this point. Well I think it likely that GNAT might implement Erhard's suggestion anyway, so in practice for Ada 2012 :-) **************************************************************** From: Robert Dewar Sent: Thursday, March 8, 2012 2:49 PM The natural exception message would be to add something about a precondition failing, easy enough to do! > Right; I have much more sympathy for that. But I think I agree with > Bob, that such inventions have to wait for Ada 2020. (Which doesn't > mean that we can't design them now and vote to add them at the next > meeting.) Joyce tells me that we need to deliver the Standard next > week, and this is definitely not the time to add new inventions. That > ended at noon on Feb 26th (that is, the end of Kemah meeting). And also doesn't mean that implementations have to wait for 2020, e.g. if we go along with Erhard's suggestion which seems very nice to me (Add Pre_Exception and Post_Exception). **************************************************************** From: Robert Dewar Sent: Thursday, March 8, 2012 2:57 PM > Fortunately, it appears that with the current Ada 2012 definition that > is entirely possible. One nasty thing is that it is going to be very hard wortk to get a decent exception message. If we adopt Erhard's approach, which I like much better than your trick, this falls out free. **************************************************************** From: Randy Brukardt Sent: Thursday, March 8, 2012 3:06 PM > > procedure Read(File : File_Type; Element: out Elem_Type) > > with Pre => Is_Open(File), Pre_Exception => Status_Error; > > with Post => valid(Element), Post_Exception => Read_Error; > > The above is an interesting suggestion, since we could implement it in > any case without needing a language extension. That was the suggestion that had the most support in Kemah. Names of secondary aspects pending. You might have noticed I used something like it in my reply to J-P the other day. (No, you obviously didn't... :-) **************************************************************** From: Randy Brukardt Sent: Thursday, March 8, 2012 3:14 PM > And also doesn't mean that implementations have to wait for 2020, e.g. > if we go along with Erhard's suggestion which seems very nice to me > (Add Pre_Exception and Post_Exception). For the record, my notes show that Tucker originally made the suggestion of using additional aspects for this purpose. I was planning to write up the AI12 that way (as that was the consensus from the Kemah ARG meeting). The other ideas are very similar to the sort of thing I originally proposed in the original AI05-0290-1, and those were not liked as much during the meeting. **************************************************************** From: Robert Dewar Sent: Thursday, March 8, 2012 3:16 PM > That was the suggestion that had the most support in Kemah. Names of > secondary aspects pending. You might have noticed I used something > like it in my reply to J-P the other day. (No, you obviously didn't... > :-) sorry missed it. I like it because getting a nice exception message comes for free, it would just share all the mechanism we have now for nice pre/post condition failure messages for exceptions. I am not sure we should try to jam it into the official 2012, but for sure, my current thinking is that we should implement this in 2012. Of course it would be nice to implement it with whatever names seem best, I think Pre_Exception and Post_Exception are rasaonable .. short and clear. **************************************************************** From: Randy Brukardt Sent: Thursday, March 8, 2012 3:17 PM > > Fortunately, it appears that with the current Ada 2012 definition > > that is entirely possible. > > One nasty thing is that it is going to be very hard wortk to get a > decent exception message. If we adopt Erhard's approach, which I like > much better than your trick, this falls out free. This seems backwards to me. Geert's trick involves writing a tiny function, and that function can trivially use "raise blah with "message"; No possible problem there (the assertion check itself is never made, because the exception happens first). (You could even make the message a parameter to the function if needed.) On the other hand, the aspect solution that you are incorrectly attributing to Erhard does not include an exception message and thus only the implementation could provide it. That would be both more work and less flexible. **************************************************************** From: Robert Dewar Sent: Thursday, March 8, 2012 3:31 PM > This seems backwards to me. Geert's trick involves writing a tiny > function, and that function can trivially use "raise blah with > "message"; No possible problem there (the assertion check itself is > never made, because the exception happens first). (You could even make > the message a parameter to the function if needed.) It would be needed and would be messy, the whole point is that the compiler supplies very nice messages about failed preconditions and postconditions (pointing to the pre or post condition involved), try it with GNAT now if you haven't seen this in action (it even points to the particular piece of the precondition that fails if you have a bunch of clauses joined by and then). But the tiny function has no idea how to raise this effectively. That's a major disadvantage to me of the Bosch trick. **************************************************************** From: Robert Dewar Sent: Thursday, March 8, 2012 3:33 PM > On the other hand, the aspect solution that you are incorrectly > attributing to Erhard does not include an exception message and thus > only the implementation could provide it. That would be both more work > and less flexible. Only the implementation has the knowledge to provide a decent message. For instance if you have a precondition with 7 clauses joined by and then, it is really useless to get a message saying one of them has failed! You need to know which one failed. More work for whom? I think GNAT gives really nice messages in this situation already, and the work is already done (to me it is an essential part of implementing Pre/Post in a compiler!) **************************************************************** From: Randy Brukardt Sent: Thursday, March 8, 2012 3:45 PM It strikes me that we might in fact be thinking about different problems here. I was thinking about a case like that for the exceptions on Put: procedure Put (File : in File_Type; Str : in String) with Pre => (Is_Open(File) or else Raise_Status_Error) and then (Mode(File) = Out_File or else Raise_Mode_Error_for_Reading (File)); (I used Geert's trick here to illustrate the issue.) Our implementation includes a message with Mode_Error that includes the name of the offending file and the expected mode. That's nothing something I would want to lose simply because we changed to using preconditions, and surely the implementation-defined message could not be so specific. Geert's technique makes that trivial (I added the file as a parameter to the raising routine in order to get that; there obviously are other ways); the aspect solution does not. OTOH, if you *don't* have a defined message, I agree that the implementation-defined one for the assertion probably provides more information than the likely to be empty message in the function created for Geert's trick. I think upon reflection that this is what you were talking about. Geert's technique also renders the concern about wanting to raise multiple different exceptions (as in the example above) moot. (Oops, sorry, can't think of a better word at the moment. ;-) I do agree that it is clunky, and we need to do better. But I wanted to point out that it actually works better in general than any of the other proposals. (Note: I'd avoid the multiple exception problem in the above by making the Is_Open part into a predicate. But it is not hard to imagine that there exist cases where you can't do that.) **************************************************************** From: Robert Dewar Sent: Thursday, March 8, 2012 4:11 PM Of course nothing we do will eliminate the Geert trick^^^^^technique **************************************************************** From: Geert Bosch Sent: Thursday, March 8, 2012 4:27 PM > One nasty thing is that it is going to be very hard wortk to get a > decent exception message. If we adopt Erhard's approach, which I like > much better than your trick, this falls out free. That is trivial. Anyway, I don't think it is appropriate to discuss implementation details on the ARG list at this time, while we should focus on Ada 2012. **************************************************************** From: Bob Duff Sent: Thursday, March 8, 2012 5:08 PM > Bob, what do you think I think we should all stop distracting Randy from the job at hand, which is to crank out an RM with minimal changes from what we've already got. Steve has done a good job of nailing down the last remaining item. I suggest we defer all talk about 2020 features and impl-def features until WG9 approves the RM. P.S. I'm going on vacation right about now... **************************************************************** From: Robert Dewar Sent: Thursday, March 8, 2012 7:35 PM > For the record, my notes show that Tucker originally made the > suggestion of using additional aspects for this purpose. I was > planning to write up the > AI12 that way (as that was the consensus from the Kemah ARG meeting). > The other ideas are very similar to the sort of thing I originally > proposed in the original AI05-0290-1, and those were not liked as much > during the meeting. Actually, thinking about this more, I am not so enthusiastic about the separate aspects. I am convinced by the argument that in general you need multiple different exceptions in the same precondition quite often. So I think it better to use Geert's technique, or (better), some specific form like Constraint_Error'Raise or raise Constraint_Error These are better since it is much easier for the compiler to provide useful default exception messages. **************************************************************** From: Randy Brukardt Sent: Thursday, March 8, 2012 7:49 PM I tend to agree. And raise Constraint_Error with "Message" (the with part being optional) is best of all, since it allows using a specific user-defined message where that makes sense. (After all, that's the form of the raise statement, so it would make sense to use a similar form in an expression.) **************************************************************** From: Robert Dewar Sent: Thursday, March 8, 2012 7:55 PM Yes, that's definitely appropriate! **************************************************************** From: Erhard Ploedereder Sent: Monday, March 12, 2012 9:02 AM > Actually, thinking about this more, I am not so enthusiastic about the > separate aspects. I am convinced by the argument that in general you > need multiple different exceptions in the same precondition quite > often. Neither am I, but then, the "real thing" would be multiple PREs, such as: procedure Set_Input(File: in File_Type) with PRE => Open(File) or else raise Status_Error with opt_MSG; with PRE => Mode(File)=In_File or else raise Mode_Error; (Interestingly, the order of the PREs matters for definedness!) **************************************************************** From: Robert Dewar Sent: Monday, March 12, 2012 9:29 AM I see no point in this, why is this different from with PRE => (Open(File) or else raise Status_Error with opt_MSG); and then (Mode(File)=In_File or else raise Mode_Error); **************************************************************** From: Erhard Ploedereder Sent: Monday, March 12, 2012 12:42 PM Halstead and McCabe metrics regard the latter as more complex, don't they? (And they probably are right, once your preconditions also contain more complicated boolean expressions, especially ones that include "and then"-expressions.) Technically, there should be no difference, of course. It is a matter of additional structure and of enabling a quick glance at all the raised exceptions when reading the spec. An equally readable "and then"-version requires a formatting discipline (as in your example) that neither people nor automated reformaters have. **************************************************************** From: Robert Dewar Sent: Monday, March 12, 2012 9:43 PM > Halstead and McCabe metrics regard the latter as more complex, don't > they? (And they probably are right, once your preconditions also > contain more complicated boolean expressions, especially ones that > include "and then"-expressions.) I find this absurd, the use of AND THEN here is just a systematic way of having multiple preconditions > Technically, there should be no difference, of course. of course > It is a matter of additional structure and of enabling a quick glance > at all the raised exceptions when reading the spec. An equally > readable "and then"-version requires a formatting discipline (as in > your example) that neither people nor automated reformaters have. Well we certainly enforce formattint discipline at AdaCore, and anyone who does not is never going to write comprehensible code anyway. And automated reformatters do have appropriate capabilities! ****************************************************************