CVS difference for ai05s/ai05-0212-1.txt

Differences between 1.3 and version 1.4
Log of other versions for file ai05s/ai05-0212-1.txt

--- ai05s/ai05-0212-1.txt	2011/01/29 02:18:54	1.3
+++ ai05s/ai05-0212-1.txt	2011/02/16 06:15:23	1.4
@@ -1,4 +1,4 @@
-!standard A.18.2(9/2)                                  11-01-28  AI05-0212-1/03
+!standard A.18.2(9/2)                                  11-02-09  AI05-0212-1/04
 !class Amendment 10-04-26
 !status work item 10-04-26
 !status received 10-02-27
@@ -47,8 +47,8 @@
           Ada.Iterator_Interfaces (Cursors, No_Element);
 
 
-Add the following to each Ada.Containers package immediately after
-Update_Element (with suitable substitutions for the names of types).
+Add the following to each Ada.Containers package (other than the Queues packages)
+immediately after Update_Element (with suitable substitutions for the names of types):
 
     type Constant_Reference_Type (Element : not null access constant Element_Type) is
        with private
@@ -71,6 +71,8 @@
 however, there is no associated container. Since this is useless, and supporting
 this case would take extra work, we define it to raise an exception.
 
+Add the following to each Ada.Containers package that has a Cursor type
+immediately after the above (with suitable substitutions for the names of types):
 
     function Constant_Reference (Container : aliased in Vector; Position : in Cursor)
        return Constant_Reference_Type;
@@ -164,7 +166,33 @@
 The Reference function for a Set and Key may need to work like the
 Update_Element_Preserving_Key routine. More thought needed.]
 
+Add the following to Ada.Containers.Indefinite_Holders and its relatives:
 
+    function Constant_Reference (Container : aliased in Holder)
+       return Constant_Reference_Type;
+
+This routine (combined with the Implicit_Dereference aspect)
+provides a convinient way to get read access to the contained element of
+a holder container.
+
+If Container is empty, Constraint_Error is propagated. Otherwise, Constant_Reference
+returns an object whose discriminant is an access value that designates the contained
+element. Program_Error is propagated if any operation tampers with the elements of
+Container while the object returned by Constant_Reference exists and has not been
+finalized.
+
+    function Reference (Container : aliased in out Holder) return Reference_Type;
+
+This function (combined with the Implicit_Dereference aspects) provides a convinient
+way to get read and write access to the contained element of a holder container.
+
+If Container is empty, Constraint_Error is propagated. Otherwise, Reference returns
+an object whose discriminant is an access value that designates the contained element.
+Program_Error is propagated if any operation tampers with the elements of Container
+while the object returned by Reference exists and has not been finalized.
+
+
+
 After the existing procedure Reverse_Iterate of each container that has Reverse_Iterate,
 add a new function:
 
@@ -286,7 +314,7 @@
 
 A.18.33 Example of container use.
 
-[** TBD - bigger, better examples are supposed to be coming from Ed and Steve. 
+[** TBD - bigger, better examples are supposed to be coming from Ed and Steve.
    Examples of iterator use need to be included. **]
 
 For the following declarations:
@@ -629,3 +657,501 @@
 (This drops A.18.19(3/3) and similar bullets.)
 
 ****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, February  7, 2011  7:28 PM
+
+Steve brings up an interesting question in some private mail: should the Ada
+strings packages have changes to incorporate iterators  and indexing?
+Presumably, we'd make those changes in this same AI.
+
+Here is a list of the various changes and how they might be used in strings
+packages:
+
+Aspect Implicit_Dereference
+   This doesn't make sense for the strings packages; we don't want to be making
+   pointers at individual characters. Requiring the individual characters to be
+   aliased to support this strategy could cause some implementations to waste a
+   lot of memory (on a word-addressable machine in particular).
+
+Aspect Constant_Indexing
+   This maps nicely on the existing function Element for the Bounded and
+   Unbounded strings. (Fixed strings, of course, already have this as an array
+   type.) So I think we should consider adding this.
+
+Aspect Variable_Indexing
+   This maps to procedure Replace_Element, but not sensibly. The current scheme
+   imagines that it maps to a function returning an access to an element (using
+   reference) -- but using an access type doesn't make much sense in this
+   context. Rather, we'd rather pass a value to a procedure to set the element.
+   That of course would require some sort of change to the currently defined
+   mechanism for Variable_Indexing. I'd guess that is too complicated to define,
+   so I think it probably would make more sense to just forget this capability.
+   (Whether this means we should forget about providing *read* access I can't
+   say.)
+
+Iterator interfaces
+   These seem like overkill here, since the indexes are integers and iterating
+   an entire object S just requires
+       for I in 1..Length(S) loop
+   But see the next item.
+
+Aspects Default_Iterator and Iterator_Element
+   These would be useful, as they would enable the string to be iterated with
+   the container syntax:
+       for Ch of My_Unb_String loop
+
+   There are a couple of issues:
+     (1) First, without Variable_Indexing, Ch could only be used in a read-only
+	 way. That might be pretty limiting.
+     (2) We'd have to define an iterator function much like we do in the
+	 containers to be used here. That adds a bit of complication (no big
+	 deal, though).
+
+   It's not clear if this is worth it.
+
+So, the only slam-dunk is Constant_Indexing. It's not clear if that alone is
+worth defining (it could be confusing that writing elements isn't supported). Or
+we could consider trying to come up with an extra mapping for Variable_Indexing
+that would map:
+    S(N) := C;
+into
+    Replace_Element (S, N, C);
+
+In which case we would want to define all of these things.
+
+Thoughts??
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, February  7, 2011  8:06 PM
+
+> Aspect Implicit_Dereference
+>     This doesn't make sense for the strings packages; we don't want to
+> be making pointers at individual characters. Requiring the individual
+> characters to be aliased to support this strategy could cause some
+> implementations to waste a lot of memory (on a word-addressable
+> machine in particular).
+
+We could generalize Implicit_Dereference a bit by having a different
+equivalence, such as "Ref" by itself is equivalent to
+"Ref.Discrim.all(Ref.Index)" or "Ref.Discrim.all.Field" and thereby avoid the
+need to have the individual elements be aliased, so long as some enclosing
+composite object is aliased.
+
+...
+> Aspect Variable_Indexing
+>     This maps to procedure Replace_Element, but not sensibly. The
+> current scheme imagines that it maps to a function returning an access
+> to an element (using reference) -- but using an access type doesn't
+> make much sense in this context. Rather, we'd rather pass a value to a
+> procedure to set the element. That of course would require some sort
+> of change to the currently defined mechanism for Variable_Indexing.
+> I'd guess that is too complicated to define, so I think it probably
+> would make more sense to just forget this capability. (Whether this
+> means we should forget about providing *read* access I can't say.)
+
+For Variable_Indexing, if we generalize Implicit_Dereference, then we can also
+generalize Variable_Indexing.
+
+...
+>     There are a couple of issues:
+>       (1) First, without Variable_Indexing, Ch could only be used in a
+> read-only way. That might be pretty limiting.
+
+But see above.
+
+...
+> Thoughts??
+
+Might be worth investigating a generalization of Implicit_Dereference which
+works with unaliased subcomponents of an aliased composite object.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, February  7, 2011  8:22 PM
+
+...
+> We could generalize Implicit_Dereference a bit by having a different
+> equivalence, such as "Ref" by itself is equivalent to
+> "Ref.Discrim.all(Ref.Index)" or "Ref.Discrim.all.Field"
+> and thereby avoid the need to have the individual elements be aliased,
+> so long as some enclosing composite object is aliased.
+
+I don't see how this helps. The public view of an Unbounded_String is a
+featureless partial view. Whether or not there is any enclosing composite object
+that is aliased is not something that the public can know about. OTOH, the
+aspects are all about the *public* view of something.
+
+I don't think it is a good idea to expose anything about the implementation of
+this type, because there probably are implementations that violate it.
+
+For instance, you could make the scheme you suggest here work if you were
+willing to require that all implementations store unbounded strings as an access
+to a string. [Then an operation that returned such a pointer could be used as an
+implicit dereference.] But that would break any implementations that use a
+chunked implementation (which might make sense if assignments/modifications are
+more common in programs than the reading operations).
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, February  7, 2011  10:28 PM
+
+> I don't see how this helps. The public view of an Unbounded_String is
+> a featureless partial view. Whether or not there is any enclosing
+> composite object that is aliased is not something that the public can know about.
+> OTOH, the aspects are all about the *public* view of something.
+
+Hmmm...  Getting creative here.  Suppose we define a new aspect
+"Private_Implicit_Dereference" which indicates that the associated type is a
+reference type which when implicitly dereferenced has the specified type:
+
+    type Element_Reference(<>) is private
+      with
+        Private_Implicit_Dereference => Character;
+
+    ...
+private
+
+    type Unbounded_String is new Finalization.Controlled with record
+        Chars : access String;
+    end record;
+
+    type Element_Reference(UStr : access Unbounded_String) is record
+        Index : Positive := 1;
+    end record
+      with
+        Implicit_Dereference => UStr.Chars(Index);
+
+Then we extend the Implicit_Dereference aspect to take not just a name of an
+access discriminant, but allow a more general name as exemplified by the above.
+
+> I don't think it is a good idea to expose anything about the
+> implementation of this type, because there probably are implementations that
+> violate it...
+
+Agreed.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, February  7, 2011  10:50 PM
+
+> Hmmm...  Getting creative here.  Suppose we define a new aspect
+> "Private_Implicit_Dereference" which indicates that the associated
+> type is a reference type which when implicitly dereferenced has the
+> specified type:
+...
+> Then we extend the Implicit_Dereference aspect to take not just a name
+> of an access discriminant, but allow a more general name as
+> exemplified by the above.
+
+That seems like a lot of mechanism for not much gain. We *really* want to be
+able to do assignments of values directly into elements of this type; I don't
+see much point in even faking a by-reference mechanism. (Note that there can be
+components that you can't usefully take an address of; this seems similar.)
+
+That's why I suggested changing Variable_Indexing so that it could work by
+calling the existing procedure Replace_Element. That also seems like quite a lot
+of mechanism, but at least it doesn't require faking something no one wants in
+the first place.
+
+That is, allow Variable_Indexing to match a procedure with three parameters,
+then convert
+    S(N) := C;
+to
+    Replace_Element (S, N, C);
+
+This would also require a bit more care with the definition of the two cases. In
+particular, for "in out" parameter passing by-copy, you would have to use
+Constant_Indexing on the way in and Variable_Indexing on the way out.
+
+The only unusual thing is that S(N) would not be the name of an object (rather
+the name of a value), so it couldn't be renamed.
+
+=============
+
+In any case, I don't want this corner case to screw up the nice proposal. So
+let's not try too hard with this one...
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, February  7, 2011  11:14 PM
+
+> That seems like a lot of mechanism for not much gain. We *really* want
+> to be able to do assignments of values directly into elements of this
+> type; I don't see much point in even faking a by-reference mechanism.
+> (Note that there can be components that you can't usefully take an
+> address of; this seems similar.)
+
+I don't understand the above paragraph.  You say we want to be able to do
+assignments directly into elements of this type, but then you don't see much
+point in faking a by-reference mechanism. These seem to be contradictory
+statements (at least to me).
+
+> That's why I suggested changing Variable_Indexing so that it could
+> work by calling the existing procedure Replace_Element. That also
+> seems like quite a lot of mechanism, but at least it doesn't require
+> faking something no one wants in the first place.
+
+This would only work for elements of a by-copy type when passing an OUT or
+IN-OUT parameter.
+
+> That is, allow Variable_Indexing to match a procedure with three
+> parameters, then convert
+>      S(N) := C;
+> to
+>      Replace_Element (S, N, C);
+>
+> This would also require a bit more care with the definition of the two
+> cases. In particular, for "in out" parameter passing by-copy, you
+> would have to use Constant_Indexing on the way in and Variable_Indexing on the way out.
+>
+> The only unusual thing is that S(N) would not be the name of an object
+> (rather the name of a value), so it couldn't be renamed.
+
+Sounds pretty ugly, particularly since it wouldn't work at all for non-by-copy
+element types.
+
+> =============
+>
+> In any case, I don't want this corner case to screw up the nice
+> proposal. So let's not try too hard with this one...
+
+Agreed.  We have much bigger fish to fry...
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, February  7, 2011  11:33 PM
+
+> I don't understand the above paragraph.  You say we want to be able to
+> do assignments directly into elements of this type, but then you don't
+> see much point in faking a by-reference
+mechanism.
+> These seem to be contradictory statements (at least to me).
+
+I don't see any reason that assignment necessarily has anything to do with a
+by-reference mechanism. The obvious counter-example is by-copy parameter passing
+-- you still can assign into such parameters; even if you can get a useful
+address for them (and you don't have to be able to), it doesn't correspond to
+any other object (and certainly not the actual).
+
+In implementation terms, Janus/Ada has the concept of assignable components that
+you can't take an address of. For instance, most bit-packed components don't
+have a machine address per se (some container does, of course). Such things will
+always be passed by copy, and assignments always require changing the entire
+"container" (in the case of bit operations, you have to do a read, some masking,
+and then a write). Setting a single bit in a packed array always falls into this
+model.
+
+I was trying to abstract this model into something that makes sense at the
+language level. For such a thing, you can *only* talk about the container and
+operations on it; it doesn't make sense to even think about references to
+individual elements because you cannot make an assignment that way, anymore than
+you can talk about setting a single bit in a word (or whatever your addressible
+unit is).
+
+Anyway, it seems obvious that this isn't going to work very easily, so it's
+probably best to leave it for Ada 2020.
+
+Which leaves the question of whether to use Constant_Indexing in Bounded_Strings
+and Unbounded_Strings now, or forget it as insufficiently helpful.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, February  7, 2011  11:58 PM
+
+> I don't see any reason that assignment necessarily has anything to do
+> with a by-reference mechanism. The obvious counter-example is by-copy
+> parameter passing -- you still can assign into such parameters; even
+> if you can get a useful address for them (and you don't have to be
+> able to), it doesn't correspond to any other object (and certainly not the
+> actual).
+
+I think we are using the term "reference" in two different ways.
+The idea of the "Private_Implicit_Dereference" is that a pointer-like thing can
+be converted into a name of a component of a data structure. It doesn't mean it
+is converted into an *address*, so it would work just fine for a packed array.
+It necessarily *starts* with going through a "true" pointer, but then it might
+refer to a subcomponent of some packed structure.
+
+> In implementation terms, Janus/Ada has the concept of assignable
+> components that you can't take an address of. For instance, most
+> bit-packed components don't have a machine address per se (some
+> container does, of course). Such things will always be passed by copy,
+> and assignments always require changing the entire "container" (in the
+> case of bit operations, you have to do a read, some masking, and then
+> a write). Setting a single bit in a packed array always falls into this model.
+>
+> I was trying to abstract this model into something that makes sense at
+> the language level. For such a thing, you can *only* talk about the
+> container and operations on it; it doesn't make sense to even think
+> about references to individual elements because you cannot make an
+> assignment that way, anymore than you can talk about setting a single
+> bit in a word (or whatever your addressible unit is).
+
+Here is where you are using the term "reference" and seem to be implying that it
+requires an address.  I was thinking that Ref.Discrim.all.Chars(Index) was a
+"reference" to a particular component of the Chars array, but there is no
+requirement that Ref.Discrim.all.Chars(Index)'Address be well defined.  Merely
+that "Ref.Discrim.all.Chars(Index)" be a variable name that can be used on the
+LHS of an assignment or passed as an OUT parameter.  Presumably it will be
+passed by copy if necessary, in the normal way.
+
+> Anyway, it seems obvious that this isn't going to work very easily, so
+> it's probably best to leave it for Ada 2020.
+
+Agreed.
+
+>
+> Which leaves the question of whether to use Constant_Indexing in
+> Bounded_Strings and Unbounded_Strings now, or forget it as
+> insufficiently helpful.
+
+I think it could be confusing to be able to use these in some contexts but not
+others.
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Tuesday, February  8, 2011  3:37 AM
+
+> Which leaves the question of whether to use Constant_Indexing in
+> Bounded_Strings and Unbounded_Strings now, or forget it as
+> insufficiently helpful.
+
+I'm hesitant (like anybody I guess), but here are some thoughts FWIW:
+
+1) This is all syntactic sugar with no new functionality. I know "it's the sugar
+   that helps the medicine go down", but I don't think we heard much complaints
+   that the string packages were too complicated to be usable, or anything like
+   that.
+
+2) We have no idea how people will receive the new forms of iterators.
+Will they adopt it immediately, or just stick to the old-fashioned way on the
+ground that it is closer to what is actually happening? No one knows.
+
+3) Extending the new iterator mechanism in the next revision of Ada if there is
+   demand for it will be easy. Undoing a last-minute extension that missed some
+   important point will not.
+
+So, I'm inclined to saying: "nice idea; take a note of it for the next
+revision".
+
+****************************************************************
+
+From: Edmond Schonberg
+Sent: Tuesday, February  8, 2011  2:42 PM
+
+I think that iteration over unbounded strings is adequately supported currently,
+and there is no need to extend the new iterator machinery to cover them. We know
+the lower bound is 1, we have the function Length, the function Element and the
+procedure Replace_Element. No one has complained that there is no direct
+indexing syntax for them, and they have not been treated as containers so far.
+I agree with Jean-Pierre that this can wait to see whether there is a perceived
+need (none so far).
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, February 10, 2011  2:12 AM
+
+...
+> 1) This is all syntactic sugar with no new functionality. I know "it's
+> the sugar that helps the medicine go down", but I don't think we heard
+> much complaints that the string packages were too complicated to be
+> usable, or anything like that.
+
+Well, I HAVE heard that. But what we can do easily won't help any of the real
+problems with these packages enough to make it worth the effort. We would need
+to tackle the string literal problem in order to do that, but we're definitely
+not going to do that this time.
+  (Which only leaves users with the
+         function "+" (S : String) return Unbounded_String renames Ada.Strings.Unbounded.To_Unbounded_String;
+   "solution", it's considered too ugly to put into the standard package. Why
+   NO solution is preferable escapes me. If I don't do the above, my programs
+   look something like:
+
+    Header := new Line_Rec'(Number => 1,
+                            Value => Ada.Strings.Unbounded.To_Unbounded_String ("============"),
+                            Next => null);
+
+which is not great for readability...)
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Thursday, February 10, 2011  3:15 AM
+
+Are you saying that the ban on use clauses hampers readability? I can't agree
+any more ;-). And I have also no problem with the renaming as "+", which was
+intended by JDI. YMMV ...
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Thursday, February 10, 2011  5:22 AM
+
+Well to me Ada.Strings.Unbounded.To_Unbounded is plain horrible compared to just
+To_Unbounded. This package is designed to be used without use clauses. People
+who ban use clauses shoot themselves in the foot in a case like this, no
+sympathy :-)
+
+BTW, I really think it is a pity that we did not add a unary operator intended
+for conversion, the use of unary "+" is a bit bogus (always fascinating to me
+how operators bring anti-use folks to their senses, almost no one wants to write
+Algebra."+"(A, B) :-) :-))
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, February 10, 2011  1:28 PM
+
+You both (maybe intentionally) missed my point. I'll use the renames here if there are more than one or two uses of "To_Unbounded_String". This is the same conditions under which I would consider using a use clause. So this sort of thing only shows up in 
the "rare usage" scenario.
+
+In any case, I don't find:
+
+      Header := new Line_Rec'(Number =>  1,
+                              Value => To_Unbounded_String ("============"),
+                              Next =>  null);
+
+to be any improvement. It is still way too long and wordy (for something that is
+logically an identity function).
+
+Also note that it is not unusual to have both Ada.Strings.Fixed and
+Ada.Strings.Unbounded in the same code; you can't "use" both or you'll never
+figure out resolution errors. (I've been there!)
+
+> BTW, I really think it is a pity that we did not add a unary operator
+> intended for conversion, the use of unary "+" is a bit bogus (always
+> fascinating to me how operators bring anti-use folks to their senses,
+> almost no one wants to write Algebra."+"(A, B) :-) :-))
+
+Sorry, I sometimes write exactly that, for two reasons:
+   (1) If there is only one operator, it takes longer to find a nearby
+       declarative part and figure out the name of the appropriate type than it
+       does to just write this in prefix notation.
+   (2) If there are resolution problems, this is good way to tell the compiler
+       exactly what you mean. Trial-and-error is often the only way to fix these
+       things, because the typical compiler error messages aren't much help for
+       fixing non-resolving expressions involving operations (there are just too
+       many of them; the typical program that I debug has more than 50 "="
+       defined and the compiler simply can't guess effectively as to the
+       intended meaning).
+
+It also should be noted that I have much less objection to use clauses when they
+are applied to overloadable entities. It's the non-overloadable entities that
+cause all of the trouble, requiring you to put *in* as much dot notation
+elsewhere as you take out locally. "use all type" will definitely let me use
+"use" clauses more often. Unfortunately, that doesn't help Ada.Strings.Unbounded
+much -- as previously noted, I think To_Unbounded_String is ridiculous with or
+without a use clause.
+
+****************************************************************
+

Questions? Ask the ACAA Technical Agent