CVS difference for ai12s/ai12-0435-1.txt

Differences between 1.2 and version 1.3
Log of other versions for file ai12s/ai12-0435-1.txt

--- ai12s/ai12-0435-1.txt	2021/06/03 02:45:18	1.2
+++ ai12s/ai12-0435-1.txt	2021/06/08 05:46:03	1.3
@@ -1,8 +1,10 @@
-!standard 4.10(6/5)                                  21-05-29  AI12-0435-1/01
+!standard 4.10(6/5)                                  21-06-07  AI12-0435-1/03
 !standard 4.10(15/5)
 !standard 4.10(26/5)
-!standard 13.13.2(9.1/5)
+!standard 13.13.2(38/4)
 !class Amendment 21-05-29
+!status Amendment 1-2012 21-06-07
+!status ARG Approved 12-0-2  21-06-03
 !status work item 21-05-29
 !status received 21-05-29
 !priority Low
@@ -95,25 +97,18 @@
   parameter is either of the first subtype of T, or as an option when T
   is scalar, the base subtype of T.
 
-(4) Modify 13.13.2(9.1/5):
+(4) Modify 13.13.2(38/4):
+  The stream-oriented attributes may be specified for any type via an 
+  attribute_definition_clause. Redundant[Alternatively, each of the specific 
+  stream-oriented attributes may be specified using an aspect_specification 
+  on any type_declaration, with the aspect name being the corresponding 
+  attribute name.] Each of the class-wide stream-oriented attributes may be 
+  specified using an aspect_specification for a tagged type T using the name 
+  of the stream-oriented attribute followed by 'Class; such class-wide aspects
+  do not apply to other descendants of T. {If not directly specified, a 
+  default implementation of a stream-oriented attribute is implicitly composed
+  for a nonlimited type, and for certain limited types, as defined above.}
 
-  {For derived types, the default implementations of the Write and Read 
-  attributes are not inherited, but are rather implicitly composed.} For
-  type extensions, the Write or Read attribute for the parent type is
-  called, followed by the Write or Read attribute of each component of the
-  extension part, in canonical order. For a limited type extension, if the
-  attribute of the parent type or any progenitor type of T is available
-  anywhere within the immediate scope of T, and the attribute of the parent
-  type or the type of any of the extension components is not available at
-  the freezing point of T, then the attribute of T shall be directly
-  specified. For untagged derived types, the Write (resp. Read) attribute
-  invokes the corresponding attribute of the parent type, if the attribute
-  is available for the parent type.
-
-[Editor's complaint: This only covers Read and Write. What about Input 
-and Output, and the class-wide versions of all of these?? I would have expected
-a general statement at the top of 13.13.2 instead of this.]
-
 !discussion
 
 (1) Its unclear to the Editor whether this is really a principle that we
@@ -129,6 +124,36 @@
 (4) 4.10(4/5) states that Put_Image is implicitly composed. We don't have
 such wording for stream-oriented attributes, though.
 
+!corrigendum 4.10(0)
+
+@dinsc
+See the conflict file for the changes.
+
+!corrigendum 13.13.2(38/4)
+
+@drepl
+The stream-oriented attributes may be specified for any type via an
+@fa<attribute_definition_clause>. Alternatively, each of the
+specific stream-oriented attributes may be specified using an
+@fa<aspect_specification> on any @fa<type_declaration>, with the aspect name
+being the corresponding attribute name. Each of the class-wide stream-oriented
+attributes may be specified using an
+@fa<aspect_specification> for a tagged type @i<T> using the name of the
+stream-oriented attribute followed by 'Class; such class-wide aspects do not
+apply to other descendants of @i<T>.
+@dby
+The stream-oriented attributes may be specified for any type via an
+@fa<attribute_definition_clause>. Alternatively, each of the
+specific stream-oriented attributes may be specified using an
+@fa<aspect_specification> on any @fa<type_declaration>, with the aspect name
+being the corresponding attribute name. Each of the class-wide stream-oriented
+attributes may be specified using an
+@fa<aspect_specification> for a tagged type @i<T> using the name of the
+stream-oriented attribute followed by 'Class; such class-wide aspects do not
+apply to other descendants of @i<T>. If not directly specified, a 
+default implementation of a stream-oriented attribute is implicitly composed
+for a nonlimited type, and for certain limited types, as defined above.
+
 !ASIS
 
 No ASIS effect.
@@ -427,5 +452,216 @@
 
 Anyway, as I stated at the outset, I've consistently lost this argument, so
 I'll go crawl back under my rock. :-)
+
+****************************************************************
+
+From: Richard Wai
+Sent: Wednesday, June 2, 2021  11:10 PM
+
+Since I pretty strongly agree with what Tuck said generally, I will just chime 
+in to say that, from a higher level engineering or design perspective, you can 
+(and I often will) make the case for declaring a new type that is exactly the 
+"same" as an existing type. If your real purpose in the use of a type is to 
+assert that some data is different than some other data with the exact same 
+representation, then you'd want separate types. Of course we all know the 
+classic example of measurement units and the like, but I don't see why this 
+couldn't also apply to (tagged) record types.
+
+As a crude example, say I have:
+
+type Contact_Information record
+   record
+      Name: Name_String;
+      Address: Address_String;
+      Email: Email_String;
+   end record;
+
+procedure Send_Email (Contact: in Contact_Information; Content: in String);
+
+In my application, I store contact information for businesses and individuals. 
+I can know, as a matter of design, that I need to treat businesses and 
+individuals very differently, but I may need to do various actions on their 
+contact info, such as sending an automated email, which might be essentially 
+the same between businesses and individuals.
+
+In this case, it makes perfect sense to define both type Individual_Contact 
+and type Business_Contact as null extensions of Contact_Information. That way
+I can be sure that nothing that expects a business contact will get a
+individual contact (unless explicitly converted). I'd of course not get that
+same protection if I was merely using subtypes.
+
+Additionally, I might (or might not) want to make selective overrides to the
+operations of the type, while inheriting the rest (such as Put_Image).
+
+So I'd disagree with your comment that "it's unlikely that one can usefully
+replace operations of a type without some additional/different data)" . In 
+this example, merely knowing that the contact is for a business rather than
+a client determines how I will interpret or use the components of the record.
+Of 
+
+I do agree with you that the generic instantiation idiom is probably evil!
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, June 3, 2021  7:40 AM
+
+>>      !discussion
+>>      (1) It's unclear to the Editor whether this is really a principle
+>>      that we want to support. OTOH, he has consistently objected to
+>>      treating null extensions specially and has lost that argument
+>>      consistently.
+
+>       As far as the proposal about null extensions identified as issue (1)
+>       above, here is the logic: ...
+ 
+>Anyway, as I stated at the outset, I've consistently lost this argument, so
+>I'll go crawl back under my rock. :-)
+
+In most cases I find that I understand your arguments when you feel strongly 
+about something, but I will admit I do not understand your strong objection 
+to the use of "null extensions" as the way to create a new tagged type that 
+is "nearly the same" as some existing type (particularly a type produced as a 
+result of a generic instantiation).  Of course if you don't like them, you
+don't have to use them, but I have many examples from my own experience where
+it seems to be the right thing to do, and does not seem to be "evil" from a 
+software engineering point of view.   So presuming other folks might have 
+similar experiences with how it is appropriate to use null extensions, we 
+should have a consistent set of language principles about null extensions, 
+and I believe the proposed fix provides that consistency.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, June 3, 2021  11:22 PM
+
+>In most cases I find that I understand your arguments when you feel strongly
+>about something, but I will admit I do not understand your strong objection 
+>to the use of "null extensions" as the way to create a new tagged type that
+>is "nearly the same" as some existing type (particularly a type produced as
+>a result of a generic instantiation). Of course if you don't like them, you
+>don't have to use them, but I have many examples from my own experience
+>where it seems to be the right thing to do, and does not seem to be "evil"
+>from a software engineering point of view.
+
+It not about not liking "null extensions"; of course one has to use them 
+often. The problem is that this special semantics substantially interferes 
+with the sort of incremental development that I (strongly) prefer. I 
+explained this in more detail in one of my responses to AI12-0083-1, so let
+me steal from that:
+
+   This is my problem with the existing null extension rule; future maintenance
+   often adds extension components, and when that happens, all of a sudden you
+   have to write a bunch more routines. That's especially annoying given the way
+   that I typically create extensions (write a null extension, override all of
+   the routines that will need overriding, with TBD bodies [raise Program_Error
+   or the like], compile to make sure everything is correct, then start
+   implementing the routines -- at which point extension components get added
+   and all of the work to check that everything is overridden has to thrown out
+   the window and redone).
+
+"All of the routines that will need overriding" include any abstract 
+ancestors, as well as routines that "obviously" will need new versions. This 
+step is very time-consuming for a complex set of types (it takes a day or more
+for the Claw Builder's types), and rather violates the principles of 
+incremental development that I've always used (long before that was a
+"thing"). (That is, always have a testable version for every few hours of
+work.) Having to redo it halfway through development is very frustrating, 
+especially as I tend to use a lot of functions returning a tagged type.
+
+If there was a way to let a regular extension use this same machinery (as 
+suggested in AI12-0083-1), this objection would be mitigated quite a bit, as
+most extension components have reasonable defaults that could be used. It
+wouldn't always work, but that's OK (can't expect the compiler to write your
+program for you in every instance!)
+
+>So presuming other folks might have similar experiences with how it is
+>appropriate to use null extensions, we should have a consistent set of
+>language principles about null extensions, and I believe the proposed fix
+>provides that consistency.
+
+The problem isn't about using null extensions, the problem is that one can't 
+easily change them into a regular extension when that (inevitably in my
+experience) needs to occur. Doing so breaks a substantial amount of the code 
+already written, and forces overriding a substantial percentage of the 
+routines.
+
+I rarely see a type that has no extension components, since it is unlikely 
+that one can write different operations using only the existing components.
+It can happen, but not very often. I realize that others use these things 
+differently, specifically finding some value in interface inheritance, so they
+might see null extensions more frequently, but it still seems rare to me.
+(Introducing otherwise unneeded types just for visibility purposes will always
+be evil to me, however; either use a "use all" for such a thing or lobby for
+a proper language fix and write out the longer names until then.)
+
+Anyway, as I said previously, I have zero expectation of winning this 
+argument -- ever -- but I detest the difference between null extensions and 
+other extensions (and the mix-in problems raised in AI12-0083-1 illustrate 
+the issues as well).
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Friday, June 4, 2021  7:10 AM
+
+Clearly the narrow issue of Put_Image is now overtaken by events.  But in the
+larger issue, I have no argument with giving more extensions the advantages of
+null extensions when it comes to automatically providing implementations of 
+functions with controlling results.  But at this point we clearly aren't going 
+to *remove* the advantages that null extensions provide, and even if we give 
+more extensions the advantages of null extensions, the proposed (now approved)
+change to Put_Image would still make sense in my view.
+
+As far as the incremental development issue, I would suggest you use a private 
+extension rather than a visible null extension in your initial extension, if 
+you are having the trouble you describe.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Friday, June 4, 2021  8:22 AM
+
+> As far as the incremental development issue, I would suggest you use a 
+> private extension rather than a visible null extension in your initial 
+> extension, if you are having the trouble you describe.
+
+Doesn't Randy also need to put in a dummy component ("TBD: Boolean := raise 
+Program_Error;" or some such)?
+
+In any case, he can't fully write the required overridings until he's decided
+what components he wants to have.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, June 4, 2021 10:21 PM
+
+...
+> Doesn't Randy also need to put in a dummy component ("TBD: 
+> Boolean := raise Program_Error;" or some such)?
+> 
+> In any case, he can't fully write the required overridings until he's 
+> decided what components he wants to have.
+
+True enough, but my primary goal is always to keep the code compilable as much
+as possible. That allows detecting errors in code I just wrote before I forget
+the details of what it is supposed to do. The sorts of unfinished sentences
+that turn up in AIs periodically appear in my code, too, and finishing them
+requires having  an idea of what they are supposed to be.
+
+It's almost always the case that I have to add additional overridings after 
+the initial bunch, but those don't interfere with compilation like the initial
+requirement to override abstract routines (and functions if it isn't a null
+exclusion) does. In a system like the Claw Builder, I typically have a root
+abstract type that everything else derives from, and that type provides
+default implementations of some routines where that makes sense -- but the
+others are abstract. This is admittedly a problem where every solution is
+lousy -- one could avoid the compilation issues by having useless default
+versions, but then the possibility of forgetting to implement something
+critical would probably cause as much trouble. One gets similar problems
+using variants and case statements in Ada, as the completeness checks
+provide the same benefits and costs. I just hate having to do it twice
+because of the null extension differences.
 
 ****************************************************************

Questions? Ask the ACAA Technical Agent