CVS difference for ais/ai-30302.txt

Differences between 1.9 and version 1.10
Log of other versions for file ais/ai-30302.txt

--- ais/ai-30302.txt	2004/09/17 04:44:35	1.9
+++ ais/ai-30302.txt	2004/10/05 22:49:25	1.10
@@ -19411,27 +19411,2158 @@
 
 ****************************************************************
 
+From: Jeffrey Carter
+Sent: Friday, September 17, 2004  1:49 AM
+
+Robert A Duff wrote:
+> 
+> It seems to me that if there's a "special" value returned in the "not
+> found" case, it is entirely Good and Right to declare a constant called
+> Not_Found or some such.  And there should be a subtype that includes
+> that value plus all the normal index values.  Whether you're putting the
+> result of Find functions in data strucutures or local variables, you
+> should use that subtype if the result might be Not_Found -- or you can
+> assert that it *will* be found by using the normal index subtype.
+
+There's a simple solution to the question of what to return if a Find 
+operation doesn't find the specified value. There is a software 
+engineering principle that a value should have one and only one 
+interpretation. Returning an index from a Find operation and having a 
+special value for the not-found case violates this principle.
+
+The solution is to use a single value to indicate if the operation found 
+the value, and a 2nd value to indicate the index at which it was found 
+if it was found:
+
+type Find_Result (Found : Boolean) is record
+    case Found is
+    when False =>
+       null;
+    when True =>
+       Index : Index_Value;
+    end case;
+end record;
+
+Now there is no requirement that the range of index values be smaller 
+than its base type (at least for the Find operation).
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Friday, September 17, 2004  9:02 AM
+
+I agree with the principle, but I think Ada doesn't have what it takes
+to do it cleanly and efficiently.  If this were, say, ML then we might
+want to do something like this.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, September 24, 2004  8:57 PM
+
+The Update_Element routine is available in all of the containers. It has the
+profile of:
+
+   procedure Update_Element
+     (Position : in Cursor;
+      Process : not null access procedure (Element : in out Element_Type));
+
+A recent discussion on comp.lang.ada points out that this requires defining
+a subprogram to make any in-place modification. That's clunky, and for
+larger objects, there really isn't any option.
+
+Matt originally had returned an access type here, but he needed a generic to
+work with user defined types, which made the solution rather clunky. It also
+required elements to be constrained (so that they could be aliased), which
+was considered ugly for definite types.
+
+With the recent approval of AI-363 and AI-318, both of these objections seem
+to have disappeared. AI-363 repeals 3.6(11), so an aliased component can be
+unconstrained. And AI-318 defines anonymous access for function returns,
+which avoids the need to introduce a named access type.
+
+So, should we reconsider a specification of:
+
+   function Update_Element (Position : in Cursor)
+       return not null access Element_Type;
+
+with Query_Element changed to:
+
+   function Query_Element (Position : in Cursor)
+       return not null access constant Element_Type;
+
+These would make most simple updates easy; the only lose is the "free"
+binding of the element to a name. Instead of:
+
+    declare
+        procedure Increment (Count : in out Natural) is
+        begin
+            Count := Count + 1;
+        end Increment;
+    begin
+        Update_Element (A_Cursor, Increment'Access);
+    end;
+
+we'd have:
+
+    declare
+        Item : Natural renames Update_Element(A_Cursor).all;
+    begin
+        Item := Item + 1;
+    end;
+
+I'm not sure that putting access types into the specification is a good
+idea, but it certainly would be easier to use. The returned access would
+need rules similar to those for cursors (so that it would be erroneous to
+use it after certain operations).    - so it would complicate the wording of
+the standard a bit.
+
+In the absence of a lot of support for this idea, we probably should stay
+with the current specification (we need to freeze this thing soon).
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Friday, September 24, 2004  9:18 PM
+
+Randy Brukardt wrote:
+
+> The Update_Element routine is available in all of the containers. It has the
+> profile of:
+> 
+>    procedure Update_Element
+>      (Position : in Cursor;
+>       Process : not null access procedure (Element : in out Element_Type));
+> 
+> A recent discussion on comp.lang.ada points out that this requires defining
+> a subprogram to make any in-place modification. That's clunky, and for
+> larger objects, there really isn't any option.
+
+I can't parse this last sentence.  What do you mean "and for
+larger objects, there really isn't any option"?
+
+> ...
+> In the absence of a lot of support for this idea, we probably should stay
+> with the current specification (we need to freeze this thing soon).
+
+Leave it as is, in my view.  Safety over convenience, and
+defining a procedure locally isn't that inconvenient, once
+you get used to the idea.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, September 24, 2004  9:35 PM
+
+> I can't parse this last sentence.  What do you mean "and for
+> larger objects, there really isn't any option"?
+
+Yuck. Let's try again:
+
+That's clunky, and for larger objects, there really isn't any alternative to
+using in-place modification.
+
+> Leave it as is, in my view.  Safety over convenience, and
+> defining a procedure locally isn't that inconvenient, once
+> you get used to the idea.
+
+Kinda my position, too, but I thought it was good to ask the wider community
+before freezing this for all time.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Saturday, September 25, 2004 12:23 AM
+
+Actually, having a function like this would simplify the API a little.  You
+could get rid of Update_Element and Query_Element, and change the Element
+function like this:
+
+   function Element (C : Cursor) return access Element_Type;
+
+This does everything Query_Element, Update_Element, and Element do.  You
+could then say:
+
+   E : ET renames Element (C).all;
+
+or
+
+   Op (Element (C).all);
+
+This is exactly analogous to the STL:
+
+  void f(vect_t::iterator i)
+  {
+    E& e = *i;
+    g(*i);
+    //...
+  }
+
+For the set, you'd want to pass a constant view, so Element would be
+declared this way:
+
+   function Element (C : Cursor) return access constant Element_Type;
+
+and then a renaming of E, like this:
+
+   E : ET renames Element (C).all;
+
+would be a constant view.
+
+This is analogous to the C++ statement:
+
+  void f(set_t::const_iterator i)
+  {
+     const E& e = *i;
+  }
+
+In the case of a map, the key selector returns a constant view, and the
+element selector returns a variable view:
+
+   function Key (C : Cursor) return access constant Key_Type;
+
+   function Element (C : Cursor) return access Element_Type;
+
+so you could say:
+
+   K : KT renames Key (C).all;
+   E : ET renames Element (C).all;
+
+where K is a constant view, and E is a variable view.  This is analogous to
+the C++ statements:
+
+  void f{map_t::iterator i)
+  {
+     const K& k = i->first;
+     E& e = i->second;
+  }
+
+****************************************************************
+
+From: Nick Roberts
+Sent: Saturday, September 25, 2004  9:19 AM
+
+This seems like such a better interface design, I say it is worth making 
+the change.
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Saturday, September 25, 2004  11:04 AM
+
+> Leave it as is, in my view.  Safety over convenience, and
+> defining a procedure locally isn't that inconvenient, once
+> you get used to the idea.
+
+Well, I don't like dangling pointers, either, but I lean the other way
+on this one:  I think being forced to move a small hunk of code away
+from where I want it, wrap it in several lines of syntax, and clutter
+the namespace with a meaningless procedure name really IS a big pain.
+(That is, forcing the programmer to make an abstraction boundary at a
+place where it's inappropriate to do so.)
+
+I view this as "safety versus readability", not "safety versus
+convenience" -- and that makes the choice not so obvious.
+If you give me Lisp lambdas, I wouldn't mind the procedure approach.
+OTOH, if you give me C++ references, the ref approach could be safe
+(I think?).
+
+****************************************************************
+
+From: Pascal Obry
+Sent: Saturday, September 25, 2004  12:57 AM
+
+ > So, should we reconsider a specification of:
+ > 
+ >    function Update_Element (Position : in Cursor)
+ >        return not null access Element_Type;
+
+Why not keep both ?
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Sunday, September 26, 2004  3:13 AM
+
+You could, but the only reason we needed the procedures is because we needed
+a reference to the in-place object.  The function gives you that, which
+obviates the need for the procedure.
+
+For the vectors and lists, you would have this:
+
+   function Element (C : Cursor) 
+      return not null access Element_Type;
+
+For the sets, you would have this:
+
+   function Element (C : Cursor)
+      return not null access constant Element_Type;
+
+For the maps, you would have these:
+
+   function Key (C : Cursor)
+      return not null access constant Key_Type;
+
+   function Element (C : Cursor)
+      return not null access Element_Type;
+
+The (in)famous wordcount program would look like:
+
+   declare
+      C : Cursor;
+      B : Boolean;
+   begin
+      Insert (M, Word, 0, C, B);
+
+      declare
+         N : Natural renames Element (C).all;
+      begin
+         N := N + 1;
+      end;
+   end;
+
+****************************************************************
+
+From: Martin Dowie
+Sent: Monday, September 27, 2004  3:10 AM
+
+This looks very elegant, readable and more comprehensible to me...
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Monday, September 27, 2004  3:51 AM
+
+> Leave it as is, in my view.  Safety over convenience, and 
+> defining a procedure locally isn't that inconvenient, once 
+> you get used to the idea.
+
+I agree.  It seems to me that returning access values is opening the door
+to all sorts of dangling pointers bugs.  Consider the case of a vector,
+which is probably implemented using one or several arrays.  Returning an
+access value designating an element means that if/when an array is
+reallocated, the access becomes dangling.  And that can happen at the drop
+of a hat.  So it would be very hard indeed for the client to prevent nasty
+bugs from happening.  I believe that safety should be of paramount
+importance when making decisions about the design of the containers: we
+don't want to add cases of erroneousness unless we absolutely have to.
+
+The alternative is to say that access values never become dangling, but
+that would unnecessarily constrain the implementation.  For instance, it
+would not be legitimate for the implementation of vectors to reallocate an
+array.
+
+Bob wrote:
+
+> Well, I don't like dangling pointers, either, but I lean the 
+> other way on this one:  I think being forced to move a small 
+> hunk of code away from where I want it, wrap it in several 
+> lines of syntax, and clutter the namespace with a meaningless 
+> procedure name really IS a big pain.
+> (That is, forcing the programmer to make an abstraction 
+> boundary at a place where it's inappropriate to do so.)
+
+I suspect that readability is in the eye of the beholder, to some extent.
+I'd rather see a crisp, 10-line subprogram gathering all the processing
+that pertain to an element (or a key), than a 500-line procedure
+squirreling away a pointer at the beginning and using it in random places
+throughout the code.
+
+Furthermore, I am not convinced that the programmer would be forced to
+create "inappropriate abstractions".  It seems to me that the operations
+that are being performed on an element are good candidates for
+encapsulation and/or reuse (remember, they don't have to be local) so most
+of the time they are exactly the abstraction you want to create.
+
+And sorry, I don't care if you have to type a few extra lines of syntax.
+
+****************************************************************
+
+From: Pascal Obry
+Sent: Monday, September 27, 2004  3:41 AM
+
+Ok, but this is only a workcount program ! In some cases the changes that
+need to be done on the element could be quite more complex. In such cases it
+would certainly better to have the procedure "callback". But well it is true
+that it is always possible to pass the result of the function to a
+procedure... Looks like the function is more versatile after all!
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Monday, September 27, 2004  4:02 PM
+
+Before I start ranting, let me say this first: I agree with whoever said
+we should provide both.  I don't think we need to be super-minimalist
+here.
+
+Pascal wrote:
+
+> Tuck wrote:
+> 
+> > Leave it as is, in my view.  Safety over convenience, and 
+> > defining a procedure locally isn't that inconvenient, once 
+> > you get used to the idea.
+> 
+> I agree.  It seems to me that returning access values is opening the door
+> to all sorts of dangling pointers bugs.  Consider the case of a vector,
+> which is probably implemented using one or several arrays.  Returning an
+> access value designating an element means that if/when an array is
+> reallocated, the access becomes dangling.  And that can happen at the drop
+> of a hat.
+
+I haven't read the entire latest version, but in the C++ STL, it doesn't
+happen at the drop of a hat.  It can happen at fairly well-defined
+places.  I hope that's still true in the Ada proposal.
+
+>...  So it would be very hard indeed for the client to prevent nasty
+> bugs from happening.
+
+Actually, it's not so hard, I think: If you call the pointer-returning
+function, immediately do .all of that, and rename the result, you get
+essentially what the pass-a-procedure interface gives you, with somewhat
+less syntactic cruft and namespace pollution.  The renaming can't
+dangle, unless you modify the data structure in the scope of the
+renaming.  (Here, by "modify the data structure" I mean things like
+adding and deleting elements -- as opposed to modifying the particular
+element we've got our hands on.)  But in the pass-a-procedure interface,
+the same is true: if you modify the data structure within that
+procedure, the parameter becomes a dangling pointer (at least, if passed
+by reference, which would usually be true in the cases we're talking
+about).
+
+>...  I believe that safety should be of paramount
+> importance when making decisions about the design of the containers: we
+> don't want to add cases of erroneousness unless we absolutely have to.
+> 
+> The alternative is to say that access values never become dangling, but
+> that would unnecessarily constrain the implementation.  For instance, it
+> would not be legitimate for the implementation of vectors to reallocate an
+> array.
+> 
+> Bob wrote:
+> 
+> > Well, I don't like dangling pointers, either, but I lean the 
+> > other way on this one:  I think being forced to move a small 
+> > hunk of code away from where I want it, wrap it in several 
+> > lines of syntax, and clutter the namespace with a meaningless 
+> > procedure name really IS a big pain.
+> > (That is, forcing the programmer to make an abstraction 
+> > boundary at a place where it's inappropriate to do so.)
+> 
+> I suspect that readability is in the eye of the beholder, to some extent.
+> I'd rather see a crisp, 10-line subprogram gathering all the processing
+> that pertain to an element (or a key), than a 500-line procedure
+> squirreling away a pointer at the beginning and using it in random places
+> throughout the code.
+> 
+> Furthermore, I am not convinced that the programmer would be forced to
+> create "inappropriate abstractions".  It seems to me that the operations
+> that are being performed on an element are good candidates for
+> encapsulation and/or reuse (remember, they don't have to be local) so most
+> of the time they are exactly the abstraction you want to create.
+
+Well, I strongly disagree with the above paragraph.
+
+First of all, a philisophical point: it is not our place, as language
+designers, to decide that certain things are "good candidates" for
+encapsulation, and then *force* programmers to encapsulate on exactly
+those boundaries.  Instead, we should be providing tools for
+encapsulation, and let programmers choose where to use them.
+
+I don't usually like "500-line squirreling" procedures either, but it's
+not our job to tell people how many lines of code are appropriate in any
+given procedure.
+
+Second, the procedures in question *do* have to be local, in nearly all
+cases, because they need more information than just the Element
+parameter.  That is, the useful (perhaps reusable) abstraction is
+probably a procedure with *two* parameters, so we would need a local
+wrapper procedure with one parameter.  Consider this example:
+
+    procedure Grind_Upon_String(S: String) is
+    begin
+        for I in S'Range loop
+            Insert_In_Table(Key => S(I), Value => I);
+        end loop;
+    end Grind_Upon_String;
+
+Kind of silly: we're inserting Key,Value pair into a table, consisting
+of the character and its index in the table.  Instead of the index in
+the table, it might well be some other local variable of
+Grind_Upon_String; you get the idea.
+
+The point is, the programmer has chosen Insert_In_Table as the
+appropriate abstraction.  Wrapping it in another abstraction gains
+nothing:
+
+    procedure Grind_Upon_String(S: String) is
+    begin
+        for I in S'Range loop
+            declare
+                procedure Insert_In_Table_With_I_As_Value
+                    (X: Character) is
+                begin
+                    Insert_In_Table(Key => X, Value => I);
+                end Insert_In_Table_With_I_As_Value;
+            begin
+                Insert_In_Table_With_I_As_Value(S(I));
+            end;
+        end loop;
+    end Grind_Upon_String;
+
+I'd be tempted to call Insert_In_Table_With_I_As_Value
+"Process_Element", which is a meaningless name -- which is appropriate,
+because it's a meaningless [non]abstraction.
+
+The fact that the above has a loop is not relevant to my point -- we've
+found an element by some means, and we want to do something with it (or
+perhaps modify it).
+
+I think if you inspect your own code, and look for cases where you're
+processing one element of some data structure (either in a loop, or
+based on a lookup, or based on some other info), you will find few cases
+where the code to process one element is exactly one call to a procedure
+with exactly one parameter (the element).
+
+Consider a simple algorithm for reversing a sequence, by moving two
+indices (or cursors!) inward from both ends.  Surely the "swap the two
+current items" code doesn't deserve its own procedure (although "swap
+two items" with two parameters probably does).
+
+> And sorry, I don't care if you have to type a few extra lines of syntax.
+
+Come on, Pascal!  Surely you know me better than that!  When I complain
+about verbosity, I'm complaining about having to read useless junk --
+not about having to type it in.  See the second Grind_Upon_String above,
+which has a lot of "noise" compared to the amount of code conveying
+useful information to the reader.
+
+By the way, whether we use an accessor-returning-pointer or
+pass-a-procedure, it seems like we need two versions: one for read-only
+access, and one for read/write access.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, September 27, 2004  5:07 PM
+
+Bob Duff wrote:
+
+> Before I start ranting, let me say this first: I agree with whoever said
+> we should provide both.  I don't think we need to be super-minimalist
+> here.
+
+I don't see the point. No one is going to write "Process" subprograms if
+they don't have to. Once we've defined access versions, we're done there.
+(It would be especially good if we could write the language rules to avoid
+dangling in most cases.)
+
+I do agree in one sense though; I see no reason to drop the convenient
+value-returning function and value-replacing procedure. Doing so would just
+clutter up the code with .alls; and you really need the procedure for
+indefinite types (because you can't change constraints via .all there - the
+objects can be constrained and would need to be reallocated).
+
+> Actually, it's not so hard, I think: If you call the pointer-returning
+> function, immediately do .all of that, and rename the result, you get
+> essentially what the pass-a-procedure interface gives you, with somewhat
+> less syntactic cruft and namespace pollution.  The renaming can't
+> dangle, unless you modify the data structure in the scope of the renaming.
+
+But there isn't a way to enforce this usage (unless the infinite
+accessibility idea flies). There would be a lot more cases of erroneous
+usage, which I know will make some reviewers nervous.
+
+> But in the pass-a-procedure interface,
+> the same is true: if you modify the data structure within that
+> procedure, the parameter becomes a dangling pointer (at least, if passed
+> by reference, which would usually be true in the cases we're talking
+about).
+
+Humm, sounds like a case that needs to be enumerated in the "Erroneous
+Execution" part of the standard. "If Element_Type is not a by-copy type,
+...."
+
+> By the way, whether we use an accessor-returning-pointer or
+> pass-a-procedure, it seems like we need two versions: one for read-only
+> access, and one for read/write access.
+
+We have Query_Element (read-only) and Update_Element (read-write) currently.
+It would expect that we'd only change to anon access returns for those, with
+no other changes to the spec. (as I noted above).
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Monday, September 27, 2004  5:18 PM
+
+I wrote:
+
+> > Before I start ranting, let me say this first: I agree with whoever said
+> > we should provide both.  I don't think we need to be super-minimalist
+> > here.
+
+Randy replied:
+
+> I don't see the point. No one is going to write "Process" subprograms if
+> they don't have to. ...
+
+That may well be true.  If so, it's good evidence that the Process
+subprogram is a bitter pill (for curing an admittedly nasty disease).
+
+> > Actually, it's not so hard, I think: If you call the pointer-returning
+> > function, immediately do .all of that, and rename the result, you get
+> > essentially what the pass-a-procedure interface gives you, with somewhat
+> > less syntactic cruft and namespace pollution.  The renaming can't
+> > dangle, unless you modify the data structure in the scope of the renaming.
+> 
+> But there isn't a way to enforce this usage (unless the infinite
+> accessibility idea flies). There would be a lot more cases of erroneous
+> usage, which I know will make some reviewers nervous.
+
+Correct.  We could put in a NOTE recommending renaming.  Whenever I
+write these sorts of return-pointer things, I put in a comment saying
+"Beware dangling pointers", and recommending renames.
+
+****************************************************************
+
+From: Ehud Lamm
+Sent: Tuesday, September 28, 2004  2:27 AM
+
+For what it's worth I am with Bob as regards this issue. The style of
+programming implied by the collection interface (as inspired by the STL and
+other collection interfaces etc.) encourges the creation of small and rather
+meaningless element processing procedures, ones that are often quite
+thightly depedent on local scope.
+
+Without "anonymous functions" this style of programming can have a bad
+impact on readability, an reliability. Notice that C#, for example, added
+"anonymous delegates" to better support this style of programming. I guess
+that's out of the question for us at this point...
+
+We should keep in mind that the renaming "trick" reuiqres deep understanding
+of the language, and is quite subtle for beginners to understand. A NOTE is
+a good idea, as well as a style guide (is there going to be a new AQ&S
+guide?)
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Tuesday, September 28, 2004  8:59 AM
+
+I had this problem today (see ai302/examples/shapes).  I needed to sort array, which looks like this:
+
+   Rect : aliased Rectangle_Type;
+   Line : aliased Line_Type;
+   Face : aliased Face_Type;
+
+   type Shape_Array is
+     array (Positive range <>) of access Shape_Type'Class;
+
+   V : Shape_Array := (Rect'Access,
+                       Line'Access,
+                       Face'Access);
+
+
+I decided to try out the fancy new array declaration syntax, that allows an anonymous access type as the array element subtype.
+
+     procedure Sort is
+         new Ada.Containers.Generic_Array_Sort
+          (Positive,
+           ???,
+           Shape_Array);
+
+I have no actual type match the Generic_Array_Sort.Element_Type formal.  To solve this problem, I came up with another kind of sorting procedure:
+
+generic
+
+   type Index_Type is (<>);
+
+   with function Less (Left, Right : Index_Type)
+       return Boolean is <>;
+
+   with procedure Swap (Left, Right : Index_Type) is <>;
+
+procedure Generic_Sort (First, Last : in Index_Type'Base);
+
+That allows me to say:
+
+   Sort_V:
+   declare
+      function Less (I, J : Positive) return Boolean is
+         IW : constant Point_Type := West (V (I).all);
+         JW : constant Point_Type := West (V (J).all);
+      begin
+         return IW.X < JW.X;
+      end;
+
+      procedure Swap (I, J : Positive) is
+         E : Shape_Type'Class renames V (I).all;
+      begin
+         V (I) := V (J);
+         V (J) := E'Access;
+      end;
+
+      procedure Sort is
+         new Generic_Sort (Positive);
+   begin
+      Sort (V'First, V'Last);
+   end Sort_V;
+
+
+I don't know if this will be a problem or not, but I thought I'd bring it up...
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Tuesday, September 28, 2004  12:11 PM
+
+Actually, I just realized that this is an issue even in Ada today, since 
+you can declare an array object whose type is anonymous:
+
+    V : array (1 .. 3) of Shape_Class_Access;
+
+We don't have a generic actual array type to match the Array_Type 
+formal.  However, the Generic_Sort declared below works for this array 
+object declaration, too.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, September 28, 2004  12:35 PM
+
+I would like to see a generic sort like that as well.
+It is probably too late to standardize it, but getting
+it into your "reference implementation" would certainly
+be a start.  I have never been completely happy with
+the array sorts we provide, since they seem unnecessarily
+"concrete."  So long as the user provides the compare
+and the swap, we really don't care what is the type of
+the "array" or array-like thing.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, September 28, 2004  2:34 PM
+
+That's true as long as you don't care about the usability and performance of
+the result. But Sort is an expensive and common operation, and specializing
+it enough to make it perform reasonably is valuable. I'd be very opposed to
+a compare and swap sort as the only one provided.
+
+To expand on that a bit, the usability issue should be obvious: you usually
+would have to write a swap routine. While the compare often already exists
+for other reasons, there almost never is a reason to have a swap.
+
+The performance issue is simply that a swap routine injects an extra
+subprogram call into the mix. Moreover, it prevents any optimization of
+element movement - you have to use a straight swap even if something better
+is available. (You can't take advantage of relinking elements or the fact
+that list sorts are stable for free this way.) For small elements, that
+overhead is substantial. (And on a generic sharing implementation, it is
+even worse. Ours has to save/restore displays on formal subprogram calls.)
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Friday, September 2, 2004  4:23 PM
+
+I was definitely not suggesting we drop the others.
+I was saying that for my personal use, I have found
+the existing ones overly "concrete."  Your mileage
+obviously varies, and I accept that.  I think Matt's
+very-generic sort would be nice to have, but I don't
+think it is worth standardizing at this point...
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Tuesday, September 28, 2004  4:16 PM
+
+Has the language been modified to allow an anonymous access type as the 
+generic formal array element subtype?
+
+generic
+    type IT is (<>);
+    type ET (<>) is limited private;
+    type Array_T is array (IT) of access ET; --legal?
+procedure GP (A : Array_Type);
+
+Can the type (with access constant element subtype):
+
+    type Array_T is array (1 .. 3) of access constant T;
+
+be passed as the actual type for generic formal array type GP.Array_T?
+
+Are there any other combinations?
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, September 28, 2004  4:28 PM
+
+> Has the language been modified to allow an anonymous access type as the
+> generic formal array element subtype?
+>
+> generic
+>     type IT is (<>);
+>     type ET (<>) is limited private;
+>     type Array_T is array (IT) of access ET; --legal?
+> procedure GP (A : Array_Type);
+
+No.
+
+> Can the type (with access constant element subtype):
+>
+>     type Array_T is array (1 .. 3) of access constant T;
+>
+> be passed as the actual type for generic formal array type GP.Array_T?
+
+No.
+
+> Are there any other combinations?
+
+Who cares? There are a lot of cases in Ada where you can't use an anonymous
+type to do something. (You can't write a type conversion or qualified
+expression, for instance.) If it hurts, don't do that. :-)
+
+Anonymous types are supposed to be a convinience feature, not a cornerstone
+of design. Use them sparingly.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 28, 2004  4:40 PM
+
+OK, but I think I gave a reasonable example.  If I declare my array this 
+way:
+
+declare
+    type Array_T is array (Positive range <>) of T_Access;
+
+    E1 : aliased T;
+    E2 : aliased T;
+    E3 : aliased T:
+
+    A : Array_T := (E1'Unchecked_Access,
+                    E2'Unchecked_Access,
+                    E3'Unchecked_Access);
+begin
+    ...
+end;
+
+The issue is that type T_Access is declared in an outer scope, and so 
+the language requires the use of 'Unchecked_Access.  However, here 
+that's simply crying wolf.
+
+I'd rather say:
+
+    A : Array_T := (E1'Access,
+                    E2'Access,
+                    E3'Access);
+
+but to do that I need to either declare a local access type, or declare 
+the array element subtype as an anonymous access type.  I was trying to 
+be sparing, so I chose the latter, but then that created the problem 
+instantiating the generic...
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, September 28, 2004  4:56 PM
+
+I will admit I never noticed that these anonymous
+access types didn't make it into generic formals.
+It seems they should, presuming we have a good
+definition for "statically matching subtypes."
+That is the requirement, in general, for component
+subtypes.  I believe we allow them in the discriminant
+part of formal discriminated types, so I don't see
+why we shouldn't allow them in the component-subtype
+definition for a formal array type.  I think this
+was an oversight rather than intentional.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, September 28, 2004  5:17 PM
+
+Actually, the syntax for formal_array_type_definition
+simply says array_type_definition, so anonymous
+access types are permitted as the component type
+in a generic formal.  So I think Randy was wrong
+in saying they weren't permitted.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, September 28, 2004  5:24 PM
+
+OK, but then we haven't defined a matching rule. Or does that somehow fall
+out?
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, September 28, 2004  7:35 PM
+
+It requires that the component subtypes match statically.
+That is defined for anonymous access types in 4.9.1(2) to
+require that the designated subtypes match statically.
+This was updated in AI-231 to also require that
+null-exclusiveness and access-to-constantness match.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Wednesday, September 29, 2004  4:20 AM
+
+> I think Randy and I were worried about two different kinds of 
+> dangling references.  I was worried about the one that would 
+> occur if you left the scope where a vector object was 
+> declared.  Randy was worrying about dangling references that 
+> would occur if you altered the vector object, with the side 
+> effect of some part of it being deallocated and then 
+> reallocated elsewhere.
+
+Thanks for the example and the clarification.  I have been watching this
+thread with total bewilderment because I had no idea what problem you were
+trying to solve.
+
+My feeling is that the restrictions that you have to impose on the
+function, in particular in the case where it returns a call to another
+function, are so drastic as to seriously cripple
+functions-returning-anonymous-accesses.
+
+> This latter problem could happen with the access-procedure 
+> approach as well, and I believe it is not possible to create 
+> a reference that is so short-lived that you can completely 
+> eliminate that problem.
+
+Well, to be honest, in the access-to-procedure approach, you could at
+least "lock" the container while you are calling the access-to-procedure,
+thereby detecting the situation where deallocation/reallocation would
+happen.  I am not saying that we should require that, but it would be a
+viable implementation option for situations where safety is a prime
+concern.  On the other hand, if you return an access to a part of the
+container, there is no way that you can prevent erroneousness.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, September 29, 2004  6:03 PM
+
+> Well, to be honest, in the access-to-procedure approach, you could at
+> least "lock" the container while you are calling the access-to-procedure,
+> thereby detecting the situation where deallocation/reallocation would
+> happen.
+
+That's an excellent idea, and one that proves a decisive advantage for the
+current approach.
+
+> I am not saying that we should require that, but it would be a
+> viable implementation option for situations where safety is a prime
+> concern.
+
+I'm not sure why we *shouldn't* require that. The check appears to be
+cheaper than the check for cursor abuse, which we've mandated. And we have
+to write the text about abuse in any case - we might as well use that to
+make it safe.
+
+In particular, while in Update_Element's Process routine, calling an
+operation on the same container for the same element that could modify the
+element would raise Program_Error. For vectors, we'd also want that to
+happen for any operation that could expand the vector or make the cursor
+ambiguous (see the Bounded Error for the definition of ambiguous).
+
+There's actually not a problem if the element is by-copy for most of those
+cases, but I'd rather that we didn't define the semantics based on
+privacy-breaking properties of the element type. And this routine will
+usually be used only on large, pass-by-reference objects.
+
+The only case where the check could get complex is if a Process routine
+called Update_Element on the same container, but a different element. We
+could outlaw that to make the check easy, or we could allow it and pay a
+price in a slightly more complex check.
+
+We need also need rules for Iterate. Checking for Iterate is more expensive
+or overly broad.
+
+Alternatively to mandating checks, we can make these cases bounded errors;
+either Program_Error is raised, or (some) element is modified. That would
+reduce the need to make checks to just deletions of nodes (and reallocations
+of vectors). I don't see any need for erroneousness. (Which should help
+selling this to the safety-first folks.)
+
+> On the other hand, if you return an access to a part of the
+> container, there is no way that you can prevent erroneousness.
+
+Right. I think that clearly states it should be left as is.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Thursday, September 29, 2004  2:06 AM
+
+> I'm not sure why we *shouldn't* require that. The check 
+> appears to be cheaper than the check for cursor abuse, which 
+> we've mandated. And we have to write the text about abuse in 
+> any case - we might as well use that to make it safe.
+
+Fine with me.  I see safety as of critical importance for these packages
+anyway.
+
+> There's actually not a problem if the element is by-copy for 
+> most of those cases, but I'd rather that we didn't define the 
+> semantics based on privacy-breaking properties of the element 
+> type.
+
+Agreed.
+
+> The only case where the check could get complex is if a 
+> Process routine called Update_Element on the same container, 
+> but a different element. We could outlaw that to make the 
+> check easy, or we could allow it and pay a price in a 
+> slightly more complex check.
+
+I could go either way.  Element-level locking is going to require an extra
+integer for each element.  No big deal for big elements, but it might be a
+significant overhead for small elements.  (You need an integer, not a
+boolean, to do the locking because of recursive calls.)
+
+> Alternatively to mandating checks, we can make these cases 
+> bounded errors; 
+
+Right, but I would be slightly in favor of making the behavior
+deterministic here.  After all, the whole point of this library is that
+you can port your code more easily.  Bounded errors can cause nasty
+porting problems.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, September 30, 2004  12:25 PM
+
+> I could go either way.  Element-level locking is going to require an extra
+> integer for each element.  No big deal for big elements, but it might be a
+> significant overhead for small elements.  (You need an integer, not a
+> boolean, to do the locking because of recursive calls.)
+
+I was thinking of a list of locked elements in the container; much less
+space overhead. Calling Update_Element a second time on the same element
+surely should be detected, so I wouldn't try to allow recursive calls. (But
+even if that is allowed, a list of locked elements still would work. The
+list would usually be small - that is 0 or 1 elements.)
+
+Note that this is another case where an "unchecked" set of containers could
+be defined in a secondary standard if the overhead really matters.
+
+> > Alternatively to mandating checks, we can make these cases
+> > bounded errors;
+>
+> Right, but I would be slightly in favor of making the behavior
+> deterministic here.  After all, the whole point of this library is that
+> you can port your code more easily.  Bounded errors can cause nasty
+> porting problems.
+
+I agree.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, September 30, 2004  12:37 PM
+
+I think mandating this is a mistake at this point.
+I think it requires too much careful analysis of
+the implementation implications.
+
+I think we should clearly define what is "evil" but
+forcing all implementations to catch all evil behavior
+is overkill, I believe.  We want the user to know
+what behavior is portable, and we can rely on implementors
+to try to catch most evil behaviors, but give up when
+it gets too hard.  By saying that the behavior is
+"unspecified" in the evil cases, we are hopefully
+making a clear indication to the user that it is
+non portable.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, September 30, 2004  1:04 PM
+
+> I think mandating this is a mistake at this point.
+> I think it requires too much careful analysis of
+> the implementation implications.
+
+I've already done that, and it is a fairly simple check. That, of course,
+depends on exactly what is prohibited.
+
+> I think we should clearly define what is "evil" but
+> forcing all implementations to catch all evil behavior
+> is overkill, I believe.
+
+I agree, but this particular case (at least the vast majority of it) is easy
+to check, without much space overhead.
+
+We can't reliably detect dangling cursors (I've tried, and have concluded it
+has to be erroneous); but this can be detected.
+
+My intent is for our implementation to detect all of the bounded error cases
+and most dangling cursors. Which demonstrates Pascal's point: moving from
+some other implementation to ours could very well cause problems, because
+we're detecting problems that the other implementation ignores.
+
+> We want the user to know
+> what behavior is portable, and we can rely on implementors
+> to try to catch most evil behaviors, but give up when
+> it gets too hard.  By saying that the behavior is
+> "unspecified" in the evil cases, we are hopefully
+> making a clear indication to the user that it is
+> non portable.
+
+Someone (perhaps it was you) told me that "unspecified" was worse than
+erroneous.
+
+When I've said "unspecified" in the containers text, I really mean that some
+result is returned, or some exception is raised. But not that unrelated
+memory is overwritten, or that the command to launch the missles is sent.
+That implies that the containers are not compiled with checks suppressed,
+for instance.
+
+I wonder if we need to be a bit tighter than a blanket "unspecified". One
+way to do it would be to define a "corrupted container", and then to say
+that any operation on a corrupted container either raises some exception,
+never returns, or returns with any function result or "out" parameters
+having unspecified values.
+
+Is this worth doing? (It would improve the safety a bit.)
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Thursday, September 30, 2004  1:21 PM
+
+> Is this worth doing? (It would improve the safety a bit.)
+
+Functions that return anonymous access types = yes.
+Adding extra safety checks = no.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Thursday, September 30, 2004  1:22 PM
+
+Obviously, I'm with Tucker.
+
+Manipulating the container (specifically, changing its cardinality) 
+during (passive) iteration is a Bad Thing to do, but a container should 
+not be required to detect this.
+
+I am in favor of functions returning anonymous access types that 
+designate container elements.  This is what the STL does, and this is 
+what Charles (sort of) does.  I'm not worried about dangling references, 
+since it's no different from:
+
+declare
+    X : Integer_Array_Access := new Integer_Array (1 .. 1);
+    I : Integer renames X (X'First);
+begin
+    Free (X);
+    I := 42;  -- dangling reference
+end;
+
+The guideline for programmers is to always rename the result of the 
+function, and to declare the object in the most inner scope possible:
+
+procedure Op (L : in out List) is  -- for example
+    C : Cursor := First (L);
+begin
+    if Has_Element (C) then
+       declare
+          I : Integer renames Query_Element (C).all;
+       begin
+          if I = 42 then
+             Delete (L, C);
+             --reference to I would be dangling here, but...
+          end if;
+       end;
+       --here there is no I to reference
+    end if;
+end Op;
+
+
+I do this all the time.  For example, I have an app that uses a list as 
+a queue.  Each list element has a reference count that indicates how 
+many objects are referring to that queue element (each object has its 
+own list cursor).  When I append a new item to the queue, or when a 
+client decrements its own contribution to the count, I inspect the 
+front-most item and delete it if the reference count is 0.  Something like:
+
+procedure Unjoin (My_Cursor : in out Cursor) is
+    E : Entry_Type renames To_Access (My_Cursor).all;
+begin
+    E.Ref_Count := E.Ref_Count - 1;
+
+    if E.Ref_Count = 0 and then My_Cursor = First (Q) then
+       Delete (Q, My_Cursor);
+       --any reference here to E would be dangling, but...
+    else
+       My_Cursor := No_Element;
+    end if;
+end Unjoin;
+--here there is no E to reference
+
+This behavior is simply a consequence of the nature of containers, which 
+are merely a mechanism for storing and accessing elements.  It's the job 
+of the container to stay out of the element's way.
+
+Worrying about a single element is the least of your problems, since the 
+entire container can go away:
+
+declare
+    C : Cursor;
+begin
+    declare
+       L : List;
+    begin
+       -- ... populate L
+       C := First (L);
+    end;
+
+    Replace_Element (C, By => 42); -- oops!
+end;
+
+As you can see, it's quite easy to have a dangling reference, even 
+without functions that return an anonymous access type.
+
+There are debug versions of the STL.  Something like that could easily 
+be done for the AI-302 containers.  A vendor could provide a specialized 
+version of the library (hey, I'd even write it) that detects errors such 
+as danging cursor references, etc, but without regard for performance. 
+When the application developer is satisfied, he can simply adjust his 
+include path to get the performance-optimized version.
+
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, September 30, 2004  1:17 PM
+
+I agree if the implementation is manageable, and
+the definition is relatively short, safety is
+worth the effort.  However, Ada doesn't always
+detect dangling references, though it makes an
+effort to minimize them.  I think we need to
+put this AI to bed very soon, so I am reluctant
+to keep fiddling with it.  I'm sure Randy feels
+the same way, so I'll trust Randy to make only
+"appropriate" changes at this point.
+
+I still see the decision about Update_Element vs.
+some kind of Element_Ptr function as up in the air.
+Do you feel a decision has been made one way or
+the other?
+
+Independent of that decision, should I put in some energy
+to define the accessibility level for anon access
+function results to at least enable safe definition
+of functions like Element_Ptr, if not for Containers,
+perhaps for other similar interfaces?  As defined now,
+the anon-access function returns don't really provide
+much of any added power or safety to the language.
+If we can come up with a definition that allows them
+to be used for things *like* Element_Ptr, that would
+seem to give them some real added value.
+
+Guidance welcomed!
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+> I agree if the implementation is manageable, and
+> the definition is relatively short, safety is
+> worth the effort.  However, Ada doesn't always
+> detect dangling references, though it makes an
+> effort to minimize them.  I think we need to
+> put this AI to bed very soon, so I am reluctant
+> to keep fiddling with it.  I'm sure Randy feels
+> the same way, so I'll trust Randy to make only
+> "appropriate" changes at this point.
+
+I agree, although I'm trying to get a feeling for what appropriate is. I'd
+appreciate some comments on whether an unqualified "unspecified" is too
+broad.
+
+> I still see the decision about Update_Element vs.
+> some kind of Element_Ptr function as up in the air.
+> Do you feel a decision has been made one way or
+> the other?
+
+Personally, I agree with Pascal. The fact that the *possibility* exists to
+avoid problems with the callback versions is a significant advantage that
+does not exist for the version that returns an access.
+
+Moreover, at this late date, we need a strong consensus to make a change.
+Given that Pascal and I are against a change in this area, I don't think we
+have that.
+
+> Independent of that decision, should I put in some energy
+> to define the accessibility level for anon access
+> function results to at least enable safe definition
+> of functions like Element_Ptr, if not for Containers,
+> perhaps for other similar interfaces?  As defined now,
+> the anon-access function returns don't really provide
+> much of any added power or safety to the language.
+> If we can come up with a definition that allows them
+> to be used for things *like* Element_Ptr, that would
+> seem to give them some real added value.
+
+I personally don't think it is worth it. I've been convinced that you can't
+completely eliminate dangling pointers, and there is no such thing as a
+little bit of erroneousness. :-)
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, September 30, 2004  1:51 PM
+
+> I am in favor of functions returning anonymous access types that
+> designate container elements.  This is what the STL does, and this is
+> what Charles (sort of) does.  I'm not worried about dangling references,
+> since it's no different from:
+>
+> declare
+>     X : Integer_Array_Access := new Integer_Array (1 .. 1);
+>     I : Integer renames X (X'First);
+> begin
+>     Free (X);
+>     I := 42;  -- dangling reference
+> end;
+
+That's the problem. This is too unsafe for many of us;
+Unchecked_Deallocation has that name for a reason!
+
+...
+> As you can see, it's quite easy to have a dangling reference, even
+> without functions that return an anonymous access type.
+
+Sure, but these are also much easier to detect than those on an access type.
+
+> There are debug versions of the STL.  Something like that could easily
+> be done for the AI-302 containers.  A vendor could provide a specialized
+> version of the library (hey, I'd even write it) that detects errors such
+> as danging cursor references, etc, but without regard for performance.
+> When the application developer is satisfied, he can simply adjust his
+> include path to get the performance-optimized version.
+
+We agreed that the Madison meeting that the default for the containers would
+be safe, and that implementers could provide "unchecked" versions for
+greater performance. You have it somewhat backwards.
+
+In any case, I don't think that these checks will have much impact on
+performance (the main cost is a bit of additional memory per element). If
+you are willing to have a 99.5% detection (which I think is the best you can
+do anyway), just comparing a pair of integer serial numbers will detect
+virtually all dangling cursors. It doesn't quite catch all problems (if the
+memory has been turned back to the OS, you might get a fault that you can't
+handle; and it's possible that some other use of the memory might happen to
+"fake" the serial number).
+
+I intend that to be our primary implementation. If it turns out that the hit
+matters for some application (and that will be proven by profiling, not
+speculation!), it would easy enough to provide an "unchecked" version.
+
+Because we can't detect *all* such accesses means that we can't require
+detection in general (thus the erroneous cases for dangling cursors). But it
+seems silly to use that to say that we shouldn't detect the easy cases (like
+deleting an element that we're actively modifying).
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, September 30, 2004  2:22 PM
+
+I think it is fine to say "unspecified" for clearly
+"evil" situations.  Trying to specify exactly what
+happens will just allow users to try to depend
+on the specified behavior.
+
+Randy Brukardt wrote:
+>>I agree if the implementation is manageable, and
+>>the definition is relatively short, safety is
+>>worth the effort.  However, Ada doesn't always
+>>detect dangling references, though it makes an
+>>effort to minimize them.  I think we need to
+>>put this AI to bed very soon, so I am reluctant
+>>to keep fiddling with it.  I'm sure Randy feels
+>>the same way, so I'll trust Randy to make only
+>>"appropriate" changes at this point.
+> 
+> 
+> I agree, although I'm trying to get a feeling for what appropriate is. I'd
+> appreciate some comments on whether an unqualified "unspecified" is too
+> broad.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, September 30, 2004  2:44 PM
+
+I think you missed the point. The wording currently uses says that the
+"behavior is unspecified". Someone privately made the claim that that allows
+*anything*, including overwritting unrelated objects or launching the
+missile. There is no need to allow *that*.
+
+So my question was whether we needed to tighten up the wording so that
+exactly what is unspecified is more clear:
+
+   The operation raises some exception; or
+   Never returns; or
+   Returns with unspecified values for any function results and
+      in out and out parameters.
+
+Note that I don't want to specify the results, only that any corruption be
+limited to the container and parameters to operations.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, September 30, 2004  3:24 PM
+
+I think any time we say "unspecified" it is possible
+for implementors to do something truly stupid.
+I don't see why we need to go out of our way
+to prevent that here.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Friday, October 1, 2004  7:56 AM
+
+> I think we need to
+> put this AI to bed very soon, so I am reluctant
+> to keep fiddling with it.  I'm sure Randy feels
+> the same way, so I'll trust Randy to make only
+> "appropriate" changes at this point.
+
+Exactly.  Based on all the traffic that I have read lately, and given
+the tight schedule constraints that we have to obey, here is my
+preference:
+
+1 - Keep Update_Element the way it is (with access-to-subprogram
+Process), and don't provide a version exposing pointers.  This has been
+discussed extensively in Phoenix, and the group disliked the pointer
+version (one Tucker Taft in particular was quite vocal).  Granted, some
+language limitations have been lifted by other AIs, but I don't see that
+it significantly affects the Phoenix decision.  Plus, the
+access-to-subprogram version can be used to build a "safe" container,
+the other cannot.
+
+2 - Don't require the container to be safe in the face of updates
+occurring during a call to Update_Element.  It's OK to let
+implementations compete on the level of checking they do.
+
+3 - Don't try to specify what is a "corrupt" container or what happens
+when you operate on such a container.  Just use "unspecified" as in the
+current write-up.
+
+4 - Give up on the idea of infinite accessibility depth for function
+results.  It's just too late for such a change.  We don't have the time
+necessary to work out the implications of that change.  In particular,
+the assume-the-worst rules for access parameters could significantly
+reduce the usefulness of functions returning an anonymous access type.
+AI 318 has been quite contentious in the past; don't rock the boat.
+
+I am going to ask Randy to update AI 302 according to 1, 2, and 3 above.
+Also, AI 318 was approved with changes at the last meeting, so I am
+going to send it to WG9 in November (after editorial review), unless
+someone asks for a letter ballot.
+
+Sorry, folks, but we have to draw the line at some point.
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Friday, October 1, 2004  1:01 PM
+
+Pascal said:
+
+> 1 - Keep Update_Element the way it is (with access-to-subprogram
+> Process), and don't provide a version exposing pointers.  This has been
+> discussed extensively in Phoenix, and the group disliked the pointer
+> version (one Tucker Taft in particular was quite vocal).  Granted, some
+> language limitations have been lifted by other AIs, but I don't see that
+> it significantly affects the Phoenix decision.  Plus, the
+> access-to-subprogram version can be used to build a "safe" container,
+> the other cannot.
+
+If we use the pass-a-procedure approach (which I still don't like, for
+reasons already stated), then we need to decide whether it's OK to
+modify the container during that procedure.  Pascal is saying here, "No,
+but implementations need not check."  But note that gave an example that
+would suggest otherwise.  He was using the return-a-pointer method, but
+the issue is the same.  Basically, his example was to do a lookup,
+returning a pointer, and then delete that element (under some
+circumstances).  The deletion happens (just) before the pointer goes out
+of scope, but the deletion is the last reference to that pointer.
+
+We need to decide whether that's a reasonable thing to do (I think so).
+If so, we shouldn't say (in the pass-a-proc method) it's an error to
+modify the container during the passed procedure.  Or (in the
+return-a-ref method) that it's an error to modify the container while
+that pointer still exists.
+
+> Sorry, folks, but we have to draw the line at some point.
+
+True.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, October 1, 2004  2:55 PM
+
+...
+> If we use the pass-a-procedure approach (which I still don't like, for
+> reasons already stated), then we need to decide whether it's OK to
+> modify the container during that procedure.  Pascal is saying here, "No,
+> but implementations need not check."  But note that gave an example that
+> would suggest otherwise.  He was using the return-a-pointer method, but
+> the issue is the same.  Basically, his example was to do a lookup,
+> returning a pointer, and then delete that element (under some
+> circumstances).  The deletion happens (just) before the pointer goes out
+> of scope, but the deletion is the last reference to that pointer.
+>
+> We need to decide whether that's a reasonable thing to do (I think so).
+> If so, we shouldn't say (in the pass-a-proc method) it's an error to
+> modify the container during the passed procedure.  Or (in the
+> return-a-ref method) that it's an error to modify the container while
+> that pointer still exists.
+
+It's absolutely unreasonable in the pass-a-proc situation, because you have
+the object, not a pointer to it. You can't even get access to the cursor in
+order to do a delete without standing on your head (you'd have to an uplevel
+access to it). That's very different than the return-a-pointer method, where
+you're in the same scope.
+
+Update_Element is intended for updates to the element. Period. Doing
+anything else in the Process procedure means that you are on very thin ice.
+If you want to delete the element, do that after you leave Update_Element
+(that's what the return-a-pointer version is doing after all). That's why
+the cases are very different, and why the pass-a-proc is preferred.
+
+Moreover, we do not want to add any erroneous cases here, and there is no
+need to do so. (On this point, I disagree with Pascal's resolution; it will
+take *more* text to make these cases erroneous, and it will save very little
+in terms of implementation. It also takes the rules out of line of the
+Update_Element definition, which isn't good either.)
+
+Note that none of this applies to Iterate, which passes a cursor. We have
+extensive rules about cursors (dangling and otherwise), and moreover it
+makes perfect sense to delete some records while iterating over them. But we
+do have to say the order of iteration is unspecified if the container is
+modified by the Process routine.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Saturday, October 2, 2004  3:58 AM
+
+> Moreover, we do not want to add any erroneous cases here, and 
+> there is no need to do so. (On this point, I disagree with 
+> Pascal's resolution; it will take *more* text to make these 
+> cases erroneous, and it will save very little in terms of 
+> implementation. It also takes the rules out of line of the 
+> Update_Element definition, which isn't good either.)
+
+Technically I agree with you.  I was under the impression that there was
+no consensus on this topic, however, and surely we cannot afford to make
+sizeable semantic changes to this AI in Atlanta.  It would be good to hear
+what other people feel.  I know that some members have expressed
+misgivings about the safety of the containers.  Now would be a good time
+to speak up...
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Saturday, October 2, 2004  7:37 PM
+
+Now having actually tried to write the wording, I've concluded my statement
+above is incorrect. We have to have an erroneous wording in any case, to
+cover for the possibility of someone calling Finalize or
+Unchecked_Deallocation on the container. While that is as likely as Pam
+Anderson marrying me, we have to cover it, and if it happened, the parameter
+to Process would be unstable as the memory would be possibly reused. OTOH,
+detecting deletions of the element itself can be done fairly cheaply, and
+would catch virtually all of the real problems.
+
+I'll include a complete write-up in the "list of changes" document for the
+update.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Tuesday, October 5, 2004  9:44 AM
+
+A question about the exact semantics of the cursor-based Swap operation 
+for vectors and lists came up during my review of the Madison API.
+
+The operation looks like this:
+
+    procedure Swap (I, J : Cursor);
+
+The question was whether cursors I and J are allowed to swap elements 
+from different containers.
+
+I think the answer is no, it's not allowed, and Program_Error is raised 
+if you try.  But I'm not sure, so I wanted to ask for clarification.
+
+The reason the question came up is that the semantics of Swap are 
+defined as follows:
+
+    procedure Swap (I, J : Cursor) is
+       EI : constant Element_Type := Element (I);
+    begin
+       Replace_Element (I, Element (J));
+       Replace_Element (J, EI);
+    end;
+
+There's nothing in this algorithm that would prohibit I and J from 
+designating elements in different containers.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, October 5, 2004  10:19 AM
+
+The minutes are very clear, P_E is raised.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Tuesday, October 5, 2004  9:28 AM
+
+I just finished reviewing the changes to the AI-302 draft that we made 
+in Madison, and I had a question that Randy suggested I post to the ARG 
+discussion list.
+
+I didn't think of it during the meeting, but the C++ STL (on which 
+AI-302 is largely based) uses the name "reserve" for the operation we 
+named Ensure_Capacity.
+
+We already have a function "Capacity" that has the same name and 
+semantics as the "capacity" vector member function in the STL.
+
+The operation "Ensure_Capacity" has the same semantics as the "reserve" 
+member function in the STL, but it has a different name.
+
+My question was whether the name "Reserve" would have been a better name 
+than "Ensure_Capacity", if only to avoid any unnecessary differences 
+between to the two APIs.  Any opinions?
+
+****************************************************************
+
+From: Robert Dewar
+Sent: Tuesday, October 5, 2004  9:30 AM
+
+I am in favor of changing the name to Reserve.
+
+Ensure_Capacity is a bit odd anyway. I certainly don't call a hotel
+to ensure capacity for my upcoming stay :-)
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, October 5, 2004  10:09 AM
+
+But with this analogy Ensure_Capacity is better, because the semantics are
+really that the hotel builds new room if you come with many friends.
+
+I could go either way, but I have a preference for having the word
+capacity somewhere in the name of this operation.  Otherwise it is not
+obvious that Reserve and Capacity are related.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Tuesday, October 5, 2004  10:24 AM
+
+But you can always say at the point of call:
+
+    Reserve (V, Capacity => N);
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, October 5, 2004  10:47 AM
+
+When Matt suggested this to me, I thought he meant
+
+    Reserve_Capacity
+
+which seemed better (at least on first thought) than Ensure_Capacity. But I
+don't like "Reserve" by itself, either.
+
+****************************************************************
+
+From: Robert I. Eachus
+Sent: Tuesday, October 5, 2004  4:00 PM
+
+I think that makes more sense.  Reserve can either be a noun or a verb.  
+Reserve_Capacity isn't completely unambiguous, but it is unlikely anyone 
+will misunderstand the intent.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Monday, October 4, 2004  7:03 PM
+
+The vectors package has operations like:
+
+   function To_Vector (Count : Count_Type)
+      return Vector;
+
+   function To_Vector (Item : Element_Type; Count : Count_Type)
+      return Vector;
+ 
+   function "&" (L, R : Vector) return Vector;
+   
+   ...etc
+
+The set package as operations like:
+
+   function Union (L, R : Set) return Set;
+
+   function Intersection (L, R : Set) return Set;
+
+   ...etc
+
+That is, each of these tagged types has primitive operations that return the
+type.   (I refer to functions that return the type as "constructors", or
+"ctors" for short.)  This means that during a derivation, the derived type
+must either be declared as abstract, or the constructors must be overridden.
+
+This is fine if your derivation is public, and the derived type is intended
+to be used as a member of that class:
+
+with Integer_Vectors;
+
+package P is 
+
+   type T is new Integer_Vectors.Vector with private;
+    ...
+end P;
+
+In this case, you probably wouldn't object too much to overriding the ctors.
+However, what I often do is to implement the full view of a type as a
+private derivation, like this:
+
+package Q is
+   type T is private;
+...
+private
+
+   package Integer_Vectors is new Vectors (Integer);
+
+   type T is new Integer_Vectors.Vector with null record;
+end Q;
+
+
+The issue here is that I am forced to override the vector ctors that were
+inherited by T.  But here I don't really care about those operations, which
+aren't used to implement T, so no one will call them anyway.
+
+I don't know whether this is an issue.  After all, you can implement the
+full view of T as a record, and declare V as a component.
+
+One possibility is to arrange for the ctors to be non-primitive, something
+like:
+
+generic
+...
+package Vectors is
+   type Vector is tagged private;
+
+   package Constructors is
+      function To_Vector (Count : CT) return Vector;
+      function To_Vector (Item : ET; Count : CT) return Vector;
+      ...
+   end Constructors;
+
+   ...
+end Vectors;
+
+In the declaration above, the constructor operations aren't primitive for
+type Vector, and so aren't inherited.  However, this does mean that to use a
+constructor, you have to make those operations visible:
+
+declare
+   V1 : Vector := Constructors.To_Vector (N);
+   use Constructors;
+   V2 : Vector := To_Vector (N);
+begin
+   ...
+end;
+
+
+The issue was on my mind, and so I just wanted to see whether anyone else
+had an opinion on the matter.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, October 4, 2004  7:58 PM
+
+I agree that sometimes it makes more sense to make
+constructors non-primitive.  Putting the constructor
+operations in a child package called "Factory" or
+equivalent is something we do here pretty frequently.
+
+However, I wouldn't consider "&" and Union/Intersection
+to be constructors.  They are operators, and they
+have operands of the type.  I think the kind
+of constructors that belong in a factory are
+typically very closely tied to the underlying
+implementation of the type, rather than to its
+abstract interface.  To_Vector is somewhat a borderline
+case, since it makes sense almost independently of
+the way the vector is implemented.  On the other
+hand, if there were a constructor that took the
+initial capacity, and perhaps a specification of
+how much to expand on each expansion, etc., that
+would seem very closely tied to a particular
+implementation, and would belong in a factory
+child, or equivalent.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, october 5, 2004  2:47 AM
+
+> In this case, you probably wouldn't object too much to 
+> overriding the ctors.
+
+The constructors are fine as they are, i.e., they should be primitive.
+
+I think the example above is the important one, and we want it to work
+right.  If we didn't expect users to extend the containers, we wouldn't
+have made them visibly tagged, right?
+
+If To_Vector is not primitive, you have no way to create a T with Count
+elements.  In particular, you cannot use an extension aggregate, because T
+is a private extension.  If you believe that To_Vector is generally useful
+(and you do) then there is no reason why it wouldn't be useful for T, too.
+And yes, you'll have to override it, but that's no big deal.
+
+> However, what I often do is to implement the full view of a 
+> type as a private derivation, like this:
+> 
+> package Q is
+>    type T is private;
+> ...
+> private
+> 
+>    package Integer_Vectors is new Vectors (Integer);
+> 
+>    type T is new Integer_Vectors.Vector with null record; end Q;
+> 
+> The issue here is that I am forced to override the vector 
+> ctors that were inherited by T.  But here I don't really care 
+> about those operations, which aren't used to implement T, so 
+> no one will call them anyway.
+
+You tell me that the constructors aren't used to implement T, but I have
+no reason to believe you.  I can imagine many reasons why you would want
+to call some of the constructors for T in the body of Q.  For instance, to
+implement "&", you could first call To_Vector to create an empty vector to
+contain the result of the catenation.
+
+If you know that you will never call a given constructor (including by
+dispatching) then you can probably write a 2-line body that returns a
+dummy value.  No big deal.
+
+Also remember that in general we want controlling results to work right.
+It would be very confusing if (as suggested by Tuck) some functions were
+primitives and others were not.  This would be likely to cause mysterious
+Tag_Errors.
+
+****************************************************************
+
+From: Florian Weimer
+Sent: Tuesday, October 5, 2004  4:32 AM
+
+> I think the example above is the important one, and we want it to work
+> right.  If we didn't expect users to extend the containers, we wouldn't
+> have made them visibly tagged, right?
+
+I thought the main motivation for making them tagged was to enable the
+industry-standard method invocation syntax for them.
+
+****************************************************************
+
+From: Nick Roberts
+Sent: Tuesday, October 5, 2004  11:58 AM
+
+Would it make sense now to allow conversion towards an extension type?
+
+A conversion:
+
+    TT(X)
+
+where X was an object of tagged type T, and T was an ancestor type of TT, 
+could be defined as being equivalent to:
+
+    TT'(X with others => <>)
+
+thus requiring any extension components to have default intialisations.
+
+It would then be possible to rescind the rule that a primitive function 
+with a controlling result is abstract or must be overridden [RM2K 3.9.3 
+(4-6)]. Well, I guess so, anyway. This was always a bit of an awkward rule, 
+wasn't it?
+
+****************************************************************
+
+From: Robert A. Duff
+Sent: Tuesday, October 5, 2004  1:15 PM
+
+> Would it make sense now to allow conversion towards an extension type?
+
+Sounds dangerous, to me.
+
+> A conversion:
+> 
+>     TT(X)
+> 
+> where X was an object of tagged type T, and T was an ancestor type of TT, 
+> could be defined as being equivalent to:
+> 
+>     TT'(X with others => <>)
+> 
+> thus requiring any extension components to have default intialisations.
+
+There's no such requirement, as far as I know.  That is, "with others =>
+<>" means "use the default, if any".  For integer components with no
+explicit ":=...", it means "default initialize it to any old garbage".
+So there's some value in requiring an explicit "<>" when that is what is
+wanted.
+
+Besides, downward conversions are view conversions, and are allowed only
+for class-wide operands, and there's a tag check.  Making TT(X)
+equivalent to an extension aggregate doesn't fit in well with that.
+
+> It would then be possible to rescind the rule that a primitive function 
+> with a controlling result is abstract or must be overridden [RM2K 3.9.3 
+> (4-6)]. Well, I guess so, anyway. This was always a bit of an awkward rule, 
+> wasn't it?
+
+I wouldn't say it's awkward -- it's necessary, to make sure the
+extension components are not forgotten.  I suppose it might make sense
+to rescind that rule when the extension is "with null record".  I think
+we considered that during the Ada 9X design, but decided it wasn't
+worthwhile to have such a special case.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, September 2, 2004  9:31 AM
+
+****************************************************************
+
 From: Matthew Heaney
-Sent: Friday, July 2, 2004  9:31 AM
+Sent: Friday, September 2, 2004  9:31 AM
 
 ****************************************************************
 
 From: Matthew Heaney
-Sent: Friday, July 2, 2004  9:31 AM
+Sent: Friday, September 2, 2004  9:31 AM
 
 ****************************************************************
 
 From: Matthew Heaney
-Sent: Friday, July 2, 2004  9:31 AM
+Sent: Friday, September 2, 2004  9:31 AM
 
 ****************************************************************
 
 From: Matthew Heaney
-Sent: Friday, July 2, 2004  9:31 AM
+Sent: Friday, September 2, 2004  9:31 AM
 
 ****************************************************************
 
 From: Matthew Heaney
-Sent: Friday, July 2, 2004  9:31 AM
+Sent: Friday, September 2, 2004  9:31 AM
 
 ****************************************************************

Questions? Ask the ACAA Technical Agent