CVS difference for ais/ai-30302.txt

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

--- ais/ai-30302.txt	2005/05/15 23:47:03	1.17
+++ ais/ai-30302.txt	2005/08/12 05:11:04	1.18
@@ -27,10 +27,644 @@
 
 !appendix
 
-[Editor's note: For mail earlier than February 6, 2004, see AI-302-3.]
+[Editor's note: For mail earlier than February 4, 2004, see AI-302-3.]
 
 ****************************************************************
 
+From: Martin Dowie
+Sent: Wednesday, February 4, 2004  8:21 AM
+
+Is package Ada.Containers.Maps.Strings[ACMS] really what is
+intended, as Ada.Containers.Maps[ACM] is generic this means
+to use ACMS a user must first instantiate ACM and then
+instantiate ACMS.
+
+Charles didn't suffer from this problem as Unbounded maps (~ACM)
+and String Maps (~ACMS) were siblings not parent/child.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Wednesday, February 4, 2004  8:57 AM
+
+>2) For routines like 'Generic_Iteration' shouldn't the 'Process'
+>   generic subprogram parameter not have a 'Stop : out Boolean'
+>   parameter? To allow early exit of the iteration, without
+>   having to raise exceptions?
+
+Just use an active iterator.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Wednesday, February 4, 2004  9:52 AM
+
+Note that that's not really the correct mode anyway: it should be inout,
+not just out, like this:
+
+   generic
+      with procedure Process
+         (Cursor : in     Cursor_Type;
+           Done   : in out Boolean) is <>;
+   procedure Generic_Iteration (Map : in out Map_Type);
+
+The problem with just out-mode is that you always have to give the
+parameter a value.  But this is wrong, since you shouldn't be compelled
+to say anything if you merely want to continue.  You should only have
+say something when you want to stop.
+
+If you only want to visit some of the items, then just use an active
+iterator, and exit the loop when you need to:
+
+   declare
+      I : Cursor_Type := First (M);
+      J : constant Cursor_Type := Back (M);
+   begin
+      while I /= J loop
+         declare
+            E : Element_Type := Element (I);
+         begin
+            --do something with E
+            exit when Predicate (E);
+         end;
+
+          Increment (I);
+      end loop;
+   end;
+
+****************************************************************
+
+From: Martin Dowie
+Sent: Wednesday, February 4, 2004  10:06 AM
+
+
+[snip]
+> If you only want to visit some of the items, then just use an active
+> iterator, and exit the loop when you need to:
+[snip]
+
+I could but wasn't part of the purpose of the library to allow us to
+do common things more easily? And I'd have to say I'd use a 'Quit'
+version a _lot_ more than the current process everything,
+every time one.
+
+I'd be delighted if both versions could be included! :-)
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Wednesday, February 4, 2004  11:16 AM
+
+Dowie, Martin (UK) wrote:
+> I could but wasn't part of the purpose of the library to allow us to
+> do common things more easily? And I'd have to say I'd use a 'Quit'
+> version a _lot_ more than the current process everything,
+> every time one.
+
+It would be helpful if you could be specific about what kind of
+container you were using.
+
+The vector has neither active nor passive iterators, which means that
+for a vector you have to use a loop anyway.
+
+For the hashed map, I would find it very odd if you needed to traverse
+only some of its elements, since elements are stored in hash order.
+What would be the nature of the predicate?
+
+The sorted set is the borderline case.
+
+****************************************************************
+
+From: Peter Hermann
+Sent: Wednesday, February 4, 2004  5:57 AM
+
+> package Ada.Strings.Case_Insensitive is
+
+indeed useful.
+expected to be overloaded for fixed and (un)bounded strings.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Wednesday, February 4, 2004  9:02 AM
+
+>Is package Ada.Containers.Maps.Strings[ACMS] really what is
+>intended, as Ada.Containers.Maps[ACM] is generic this means
+>to use ACMS a user must first instantiate ACM and then
+>instantiate ACMS.
+
+That's definitely a bug in the report.  The string-key map is not a
+child of a generic.  Maybe we should do this:
+
+package Ada.Containers.Maps
+package Ada.Containers.String_Maps
+
+****************************************************************
+
+From: Marius Amado Alves
+Sent: Wednesday, February 4, 2004  9:07 AM
+
+Yes, please change that. There is a steady requirement that a single
+instantiation must be enough to get a container.
+
+****************************************************************
+
+From: Pascal Obry
+Sent: Wednesday, February 4, 2004 10:10 AM
+
+> The problem with just out-mode is that you always have to give the
+> parameter a value.  But this is wrong, since you shouldn't be compelled
+> to say anything if you merely want to continue.  You should only have
+> say something when you want to stop.
+
+Agreed, this is the way iterators are designed in the POSIX 1003.5 standard
+for example.
+
+****************************************************************
+
+From: Marius Amado Alves
+Sent: Wednesday, February 4, 2004  9:02 AM
+
+> 2) For routines like 'Generic_Iteration' shouldn't the 'Process'
+>    generic subprogram parameter not have a 'Stop : out Boolean'
+>    parameter? To allow early exit of the iteration, without
+>    having to raise exceptions?
+
+Indeed some people ban the use of exceptions for control flow. I guess they
+are not a majority in the committee. Fortunately ;-)
+
+/* However to take the exception route the exception should be defined.
+(Exit/Terminate_Immediately, _Now, _Prematurely?) Or a specification be made
+of what exceptions the iterator is guaranteed to propagate. Simply "all"
+would do. Maybe this is already there. I'm sorry, I didn't had time to read
+the AI fully yet. */
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, February 4, 2004  8:55 PM
+
+Marius Amado Alves wrote:
+
+> Sorry for my poor knowledge of ARG procedure.
+> Does this step mean the library is secured for Ada 2005?
+
+What it means is that the study committee has issued a report. No more, and
+no less. I would hope that we know more after the March ARG meeting, but
+there is no guarantee that we'll work on it (we never seem to get to
+everything on the agenda - we didn't work on AI-351, Time Ops in San Diego,
+for instance).
+
+Primarily, we just "cleaned up" Matt Heaney's proposal. We didn't change (as
+opposed to remove) functionality, with the exception of the Map container
+(where we reverted to a design more like the one Charles actually uses -
+with Matt's input). So the vast majority of design decisions are Matt's --
+we'd prefer to avoid design-by-committee.
+
+Martin Dowie wrote:
+
+> Is package Ada.Containers.Maps.Strings[ACMS] really what is
+> intended, as Ada.Containers.Maps[ACM] is generic this means
+> to use ACMS a user must first instantiate ACM and then
+> instantiate ACMS.
+
+Nope, that's clearly a bug. String_Maps ought to be usable by itself (it
+doesn't depend on the other package at all). (And this one is my fault, for
+not noticing the effect of the change.)
+
+And later, replying to Matt:
+
+>[snip]
+>> If you only want to visit some of the items, then just use an active
+>> iterator, and exit the loop when you need to:
+>[snip]
+
+>I could but wasn't part of the purpose of the library to allow us to
+>do common things more easily? And I'd have to say I'd use a 'Quit'
+>version a _lot_ more than the current process everything,
+>every time one.
+
+My understanding of Matt's design is that you use the passive iterator when
+you want to process everything (which is by far the most common), and you
+use an active iterator when you want to process part of the items. You might
+use an exception to terminate iteration in an error case, but not if you
+intended only to process part of the items. (Of course, there is no law
+requiring that, so YMMV!)
+
+I hadn't noticed that there is no passive iterator for vectors until Matt
+pointed it out last night (about 20 minutes before we released the report!).
+Consistency would suggest that there should be one, but note that it is
+easier to write an active iterator for a vector than it is to  write a
+passive one:
+
+    for I in First(Vect) .. Last(Vect) loop
+        -- Do whatever.
+    end loop;
+
+versus
+
+    declare
+       procedure Process (I : in Index_Subtype) is
+       begin
+           -- Do whatever.
+       end Process;
+       procedure Do_It_All is new Generic_Iterator (Process);
+    begin
+       Do_It_All (Vect);
+    end;
+
+Besides being longer and harder to read, you have to know or look up the
+index subtype for the vector in order to write this. So we reached no
+conclusion about that in the 20 minutes we had to think about it.
+
+Marius Amado Alves wrote:
+
+> /* However to take the exception route the exception should be defined.
+> (Exit/Terminate_Immediately, _Now, _Prematurely?) Or a specification be
+made
+> of what exceptions the iterator is guaranteed to propagate. Simply "all"
+> would do. Maybe this is already there. I'm sorry, I didn't had time to
+read
+> the AI fully yet. */
+
+The wording for Generic_Iteration for a Map says:
+
+Generic_Iteration calls Process with a cursor that designates each
+node in the Map. Any exceptions raised during Process are propagated.
+
+So it's covered. This is important, because it means that the implementation
+must be able to clean itself up (if any is needed) when an exception
+propagates - it can't leave the Map in an unstable state.
+
+****************************************************************
+
+From: Jeffrey Carter
+Sent: Wednesday, February 4, 2004  8:53 PM
+
+AI-302-03 asks
+
+> Anybody got better wording [for the quality of the String hashing
+> function]? Matt was nice enough to ignore these definitions
+> completely!
+
+See
+
+P. K. Pearson, "Fast Hashing of Variable-Length Text Strings," Comm.
+ACM, 1990 Jun
+
+It describes a "hashing function specifically tailored to
+variable-length text strings." It says that "similar strings are not
+likely to collide." (An implementation can be found in
+PragmARC.Hash_Fast_Variable_Length.) Perhaps you might think this last
+quote is "better wording".
+
+The actual algorithm produces 8-bit hash values, which may no longer be
+considered adequate, given
+
+> Hash_Type'Modulus shall be at least as large as the smaller of
+> System.Max_Binary_Modulus and 2**32.
+
+I have some comments on the proposal:
+
+The proposal has a structure called a "Vector" which is actually a list,
+which is a sequence that allows insertions and deletions at any point.
+"Vector" refers to a mathematical concept related to matrices to most
+software engineers. It may be that the STL refers to lists as vectors,
+but I hope we do not have to follow C++'s mistakes.
+
+Further, the proposal requires an inefficient array implementation, and
+several of the operations refer to this implementation. I think this is
+a mistake. Specify an general, unbounded list and let the implementor
+choose the implementation (which could be an array). As the proposal
+points out, correctly implementing a general list is not trivial, so it
+makes sense for a standard library to provide a list.
+
+Maps and sets also specify a specific implementation.
+
+If the intention is to have an extensible array structure, then I
+suggest that they be called Extensible_Arrays.
+
+Vector should have an iterator, in addition to allowing the user to
+explicitly iterate over the structure.
+
+> Open issue: This function returns a value that doesn't depend on it's
+>  parameter. It possibility could be removed in favor of just saying
+> Index_Type'Pred(Index_Type'First) appropriately. Committee discussion
+>  with the original proposal's author was inconclusive.
+
+I'd say that it should be a constant, not a function. The same seems to
+hold for First.
+
+Given that Back is defined as Index_Type'Succ (Last (Vector) ), and Last
+(Vector) could be Index_Type'Last, there seems to be a problem. There
+should be an assertion that Index_Type'Base'Last > Index_Type'Last.
+
+All the problems with Index_Type disappear with a general list, which
+would use a cursor.
+
+I would propose that the sort algorithm be made available to users for
+normal array types as well as for vectors. That would involve putting it
+in its own library unit and refering to that unit in Vectors.
+
+The Map structure is required to be implemented with a hash table. If
+we're going to have such a requirement, it should at least be named
+Hashed_Maps.
+
+An important thing about maps is that they provide fast searching,
+typically based on a lower-level structure such as a hash table or
+balanced tree. Such structures have uses of their own in addition to
+creating maps, and independent of the key/value concept of a map. For
+example, an application may collect a number of values and then need to
+quickly determine if a value is in that collection, and a searchable
+structure with a Get_First operation can be used for a priority queue.
+None of these applications use key/value pairs. Therefore, I think it's
+important to provide the underlying searchable structure to users.
+(Indeed, given the ease with which a user can wrap a key/value pair in a
+record, define comparison operations for that record that only use the
+key part, and create a map structure, given the existence of a
+searchable structure, it could be argued, since the proposal states that
+easily implemented structures should not be part of the library, that
+the library should only supply searchable structures, and not maps.)
+
+Do we really need Maps.[Wide_]Strings, given that an Unbounded_String
+can be used for the key type, and that this library should not be used
+for applications in which the use of Unbounded_Strings is not acceptable?
+
+The Sets package is mostly incomprehensible. Sets deal with elements,
+and operations must include testing if an element is in a set, creating
+a set from a list of elements (set "literals"), and set union,
+intersection, difference, and symmetric difference. Except for the
+membership test, these are missing from the package, so I don't see what
+it has to do with sets. It appears to be a searchable structure, not a
+set. This is corroborated by the package Generic_Keys, which allows the
+structure to be used as a map.
+
+The discussion of the package begins by talking about nodes, which is an
+undefined term. The reader has no idea what it has to do with the
+package, which is not specified in terms of nodes.
+
+"Sans" is a French word. Since the ARM is in English, we should use the
+English "without" instead. "No" might also be acceptable.
+
+I'd like to thank the select committee for their work. No library will
+completely please everyone. I will welcome any standard container
+library in Ada 0X.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, February 4, 2004  9:24 PM
+
+The term "vector" for extensible array is used in Java
+as well.  I think we should strive to use terminology
+that has become widely used in the programming community.
+
+I personally consider an extensible array (i.e. a vector) a useful and
+important standard container.  I don't feel the same way about a linked
+list, because it is so easy to implement what you want, and there
+are so many options when it comes to how to link the objects
+together that having a standard container for that hardly
+seems worthwhile (IMHO).
+
+So we settled on Vector, Map, and Set as three basic yet
+important abstractions that will help lift the level of
+programming above arrays and records.  In my experience
+with using languages that have large container libraries,
+it is these three that are used more widely than all
+the others combined.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, February 4, 2004  9:29 PM
+
+I agree with one caveat: we're already adding something else called "Vector"
+to the standard (see AI-296), and two might just be too confusing.
+
+But, the container vector is more useful than the list container (because of
+the calculated O(1) access to elements). And they're too similar to support
+both when we're trying to support something managable.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, February 4, 2004  9:39 PM
+
+Jeffrey Carter said:
+...
+> Further, the proposal requires an inefficient array implementation, and
+> several of the operations refer to this implementation. I think this is
+> a mistake. Specify an general, unbounded list and let the implementor
+> choose the implementation (which could be an array). As the proposal
+> points out, correctly implementing a general list is not trivial, so it
+> makes sense for a standard library to provide a list.
+>
+> Maps and sets also specify a specific implementation.
+
+No, an implementation is suggested (in AARM notes), as are performance
+characteristics. That was one of the larger changes to Matt's original
+proposal. If we made that change incompletely somewhere, that needs to be
+fixed.
+
+That said, the most important thing is that all implementations have
+consistent performance characteristics (so that porting a program from GNAT
+to ObjectAda doesn't fail for performance reasons). If GNAT used an array
+implementation and ObjectAda used a list implementation for a Vector, access
+to elements (which would be O(N) on the imagined OA implementation) could be
+too slow for the port to be viable. That needs to be avoided. OTOH,
+specifying too much about the implementation would prevent using a better
+one -- in that case, we might as well just specify the source code of the
+entire library (including the bodies!), and we don't need all of this
+wording!
+
+> I would propose that the sort algorithm be made available to users for
+> normal array types as well as for vectors. That would involve putting it
+> in its own library unit and refering to that unit in Vectors.
+
+Bad idea. To do that, you'd need provide generic formal accessor functions;
+that would have a huge overhead of function calls for both Vectors and
+Arrays. On a code shared implementation like Janus/Ada, it probably would
+run ten times slower than the specified one.
+
+If we want an array sort, we should declare one:
+
+    generic
+       type Index_Type is (<>);
+       type Element_Type is private;
+       function "<" (Left, Right : Element_Type) return Boolean is <>;
+       type Array_Type is array (Index_Type) of Element_Type;
+    procedure Ada.Generic_Sort (Arr : in out Array_Type);
+
+(We'd need an unconstrained version, too.) But keep it separate from the
+Vector one (or any List one, for that matter).
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Thursday, February 5, 2004  9:31 AM
+
+I have hosted a reference implementation at my Earthlink home page:
+
+<http://home.earthlink.net/~matthewjheaney/charles/ai302-20040205.zip>
+
+For now it only includes the vector.  There's a test_sort program in
+there too, so you have something you can run.
+
+I'll have the set and maps done in a few days.
+
+****************************************************************
+
+From: Robart A. Duff
+Sent: Thursday, February 5, 2004  10:13 AM
+
+Thanks, Matt!
+
+****************************************************************
+
+From: Jeffery Carter
+Sent: Thursday, February 5, 2004  10:58 AM
+
+Randy Brukardt wrote:
+
+> No, an implementation is suggested (in AARM notes), as are performance
+> characteristics. That was one of the larger changes to Matt's original
+> proposal. If we made that change incompletely somewhere, that needs to be
+> fixed.
+
+The normative text for vectors says
+
+"A vector container object manages an unconstrained internal array"
+
+That specifies an array implementation.
+
+> Bad idea. To do that, you'd need provide generic formal accessor functions;
+> that would have a huge overhead of function calls for both Vectors and
+> Arrays. On a code shared implementation like Janus/Ada, it probably would
+> run ten times slower than the specified one.
+
+Given that an array implementation is specified, there is no need for
+formal accessor functions. The vector can simply call an instantiation
+of the sort with the appropriate slice of its internal array. Since we
+require such an algorithm to exist, and it is useful to many users, it
+makes sense for it to be available outside the vector package.
+
+> If we want an array sort, we should declare one:
+>
+>     generic
+>        type Index_Type is (<>);
+>        type Element_Type is private;
+>        function "<" (Left, Right : Element_Type) return Boolean is <>;
+>        type Array_Type is array (Index_Type) of Element_Type;
+>     procedure Ada.Generic_Sort (Arr : in out Array_Type);
+>
+> (We'd need an unconstrained version, too.) But keep it separate from the
+> Vector one (or any List one, for that matter).
+
+If we only have one, I'd prefer it to be unconstrained. That allows
+operations such as the vector sort discussed above, where the size of
+the slice may change from call to call, without repeated instantiations.
+
+Sort for a list is a different creature. Merge sort is a good choice
+there, since a list already has the O(N) additional space that merge
+sort requires for array sorting (in the links), provided you have access
+to the list internals. Thus you get O(N log N) time in all cases and
+O(1) space.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, February 5, 2004  3:23 PM
+
+Jeff Carter wrote:
+
+> The normative text for vectors says
+>
+> "A vector container object manages an unconstrained internal array"
+>
+> That specifies an array implementation.
+
+Precisely my point. That is intended to say that there is a logical array in
+the container, but not necessarly an actual one. Matt's descriptions were
+too implementation-specific, and we moved most of that. But I'm not
+surprised that some was missed.
+
+...
+> Given that an array implementation is specified, there is no need for
+> formal accessor functions. The vector can simply call an instantiation
+> of the sort with the appropriate slice of its internal array. Since we
+> require such an algorithm to exist, and it is useful to many users, it
+> makes sense for it to be available outside the vector package.
+
+There is no intent that an array implementation is specified (it certainly
+won't be implemented that way on Janus/Ada); only that the performance
+characteristics are similar (or better) than that of an array
+implementation.
+
+In any case, I have no idea how an external generic would be able to mess
+around with the internal array - it certainly can't see it! You'd have to
+put the sort into the spec in order to do that -- and that's whats proposed
+and what you're objecting to.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Thursday, February 5, 2004  3:40 PM
+
+Randy Brukardt wrote:
+
+> Precisely my point. That is intended to say that there is a logical array in
+> the container, but not necessarly an actual one.
+
+Yes, exactly.  This allows the implementor to leave the type system in
+order choose the optimal implementation for the vector container.
+
+An implementor can use any implementation that satisfies the property
+that insertion at the back end is (amortized) constant time, and the
+property that random access is constant time.
+
+****************************************************************
+
+From: Jeffrey Carter
+Sent: Thursday, February 5, 2004  6:52 PM
+
+Randy Brukardt wrote:
+
+>>The normative text for vectors says
+>>
+>>"A vector container object manages an unconstrained internal array"
+>>
+>>That specifies an array implementation.
+>
+> Precisely my point. That is intended to say that there is a logical array in
+> the container, but not necessarly an actual one. Matt's descriptions were
+> too implementation-specific, and we moved most of that. But I'm not
+> surprised that some was missed.
+
+I read it as specifying an implementation. I suggest the wording be
+revised to make it clear that the discussion is of a logical array, not
+a requirement for an actual array.
+
+> In any case, I have no idea how an external generic would be able to mess
+> around with the internal array - it certainly can't see it! You'd have to
+> put the sort into the spec in order to do that -- and that's whats proposed
+> and what you're objecting to.
+
+I guess I wasn't clear. You would provide the external sort, and also
+specify the sort in the spec, with wording that the sort has the same
+characteristics as the external sort. This is based on the assumption
+that an array implementation is specified, so the sort algorithm, useful
+on arrays, must exist anyway.
+
+I'm reminded of my surprise that Ada-83 compilers had to support
+inifinte-precision arithmetic, but the language did not require that it
+made available to users. If the compiler writers have to implement the
+functionality, why not make it available to users? Case-insensitive
+string comparison is a similar thing: compilers have to recognize that
+frog, Frog, and FROG are the same identifier, but are (were) not
+required to make such comparisons available to users.
+
+****************************************************************
+
 From: Jeffrey Carter
 Sent: Thursday, February 5, 2004  11:38 AM
 
@@ -28347,6 +28981,42 @@
 ****************************************************************
 
 From: Matthew Heaney
+Sent: Monday, March 28, 2005  9:43 PM
+
+The description of Find (for vector) says:
+
+START OF QUOTE:
+
+196/2 function Find (Container : Vector;
+                     Item      : Element_Type;
+                     Position  : Cursor := No_Element)
+         return Cursor;
+
+    197/2 {AI95-00302-03} ... If no equal element
+          is found, then Find returns No_Cursor....
+
+END OF QUOTE.
+
+
+The description of Reverse_Find says:
+
+200/2 function Reverse_Find (Container : Vector;
+                             Item      : Element_Type;
+                             Position  : Cursor := No_Element)
+         return Cursor;
+
+     ...If no equal element
+          is found, then Reverse_Find returns No_Cursor...
+
+END OF QUOTE.
+
+
+This looks like a type, since there is no entity having the name
+"No_Cursor".  (I think "No_Element" was intended.)
+
+****************************************************************
+
+From: Matthew Heaney
 Sent: Friday, April 5, 2005 12:57 AM
 
 AA-A.TXT says:
@@ -28977,6 +29647,1777 @@
 Or is this a bug in the RM?  If so, then which Splice is correct?
 
 ENDMJH.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 15, 2005  9:34 AM
+
+The ARG is having its next meeting soon, and so I'd like reiterate my 
+position that the index-based form of Delete for vector have the 
+semantics described below.
+
+In summary:
+
+The Index parameter of Delete should have subtype Extended_Index.  (This 
+is already the case in the current AI draft.)
+
+If Index is outside of the range Index_Type'First .. Last_Index (V) + 1 
+then raise Constraint_Error.
+
+Let N be the minimum of the Count parameter, and the value of the 
+expression Last_Index (V) - Index + 1.  If N is 0 then do nothing. 
+Otherwise delete N elements starting at Index.
+
+In particular, the Index value Last_Index (V) + 1 is never an error. 
+(When Index has that value, then N is 0, and so Delete does nothing.)
+
+****************************************************************
+
+From: Marius Amado Alves
+Sent: Wednesday, April 20, 2005  6:52 AM
+
+I've prepared this Index to Ada.Containers for personal study, but that 
+others may find useful:
+
+http://www.softdevelcoop.org/software/ada_containers/
+
+****************************************************************
+
+From: Duncan Sands
+Sent: Thursday, April 21, 2005  1:58 AM
+
+I get:
+
+An error occurred while loading
+http://www.softdevelcoop.org/software/ada_containers/:
+Unknown host www.softdevelcoop.org
+
+****************************************************************
+
+From: Orville E. Wheeler
+Sent: Thursday, April 21, 2005  12:24 PM
+
+I downloaded it with no trouble using Mozilla running under
+Windows 2000.
+
+****************************************************************
+
+From: Marius Amado Alves
+Sent: Sunday, April 24, 2005  9:27 PM
+
+The Index to Ada.Containers
+
+   http://www.softdevelcoop.org/software/ada_containers/
+
+has been improved:
+
+- it is now generated directly from the AI302 text
+
+- it includes the operations of nested package Generic_Keys (Sets)
+
+- the Name Index (formerly Name Table) is in alphabetical order
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Wednesday, April 20, 2005  10:52 AM
+
+START OF QUOTE:
+
+   procedure Delete (Container : in out Set;
+                     Item      : in     Element_Type);
+
+   procedure Exclude (Container : in out Set;
+                      Item      : in     Element_Type);
+
+   procedure Delete (Container : in out Set;
+                     Position  : in out Cursor);
+
+
+END OF QUOTE.
+
+MJH:
+
+I think this is incorrect, since the same operations in the hashed_sets are
+declared in the order Delete, Delete, Exclude.
+
+ENDMJH.
+
+****************************************************************
+
+From: Marius Amado Alves
+Sent: Thursday, April 21, 2005  8:00 AM
+
+File AI95-00302-03/11, version 1.19, on Ada-Auth.Org, right?
+
+There, and in the 'secret' AARM, Length for Lists returns Natural, 
+whereas for all other containers it returns Count_Type. Is that 
+intended?
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Thursday, April 21, 2005  8:08 AM
+
+I assume that's a bug.  All of the containers (including list) use
+Count_Type to indicate cardinality.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Friday, April 22, 2005  2:54 AM
+
+Agreed, this needs fixing.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Thursday, April 21, 2005  8:32 PM
+
+In the latest AI-302 draft, A.18.7 (Sets) says:
+
+START OF QUOTE:
+
+procedure Replace_Element 
+  (Container : in Set;
+   Position  : in Cursor;
+   By        : in Element_Type);
+
+If Position equals No_Element, then Constraint_Error is propagated. If
+Position does not designate an element in Container, then Program_Error is
+propagated. Otherwise, the element designated by Position is tested for
+equivalence to By; if they are found to be equivalent, Replace_Element
+assigns By to the element designated by Position. Otherwise, the element
+designated by Position is removed from the container, then By is inserted
+into the container. If the insertion fails, Program_Error is propagated.
+
+END OF QUOTE:
+
+MJH:
+
+Should the Position parameter have mode inout?  If By isn't equivalent to
+the element designated by Position, then the node is deallocated, which
+would leave Position with a dangling reference.
+
+As it stands now, unless there's an exception (because the insertion
+failed), then this operation is silent about the fact that the element's
+node was deallocated.  The caller might have a dangling cursor, or he might
+not, and he has no way of knowing.
+
+Furthermore, if the insertion fails, then the cardinality of the set would
+have changed, since that node would have been deleted from the set.  Yet the
+set is passed using in-mode, so really we have no way of doing what is even
+specified here.  I thought the point of passing the container as a parameter
+was because Replace_Element was like an optimized Delete followed by Insert,
+both of which change cardinality.
+
+Thinking about it more, the behavior of this operation is inconsistent with
+Insert.  If we attempt to Insert an item, and an equivalent item is already
+in the set, then in the 4-parameter Insert we pass back a Boolean that has
+the value False, and in the 2-parameter Insert, we raise Constraint_Error.
+
+There are really 3 outcomes:
+
+(1) By is equivalent to the element on the node designated by Position, so
+we assign By to that element (and the assignment succeeds).
+
+(2) By is not equivalent to the element on the node designated by Position,
+so we delete the node from the set, insert By into the set, and the
+insertion succeeds (because there's no other element in the set equivalent
+to By).
+
+(3) By is not equivalent to the element on the node designated by Position,
+so we delete the node from the set, and attempt to insert By into the set,
+but the insertion fails (because there's an element already in the set
+equivalent to By).
+
+Throw in the fact that in (1) the assignment step can fail, and in (2) and
+(3) the Delete step can fail during deallocation of the node, and the
+Insertion step can fail because of allocation or initialization failure, and
+that's even more possibilities.
+
+This operation is confusing, error-prone, and dangerous.  The only benefit
+seems to be that in some situations it avoids having to perform a search.
+
+In any event here are some ideas.  Suppose that this operation is analogous
+to the 4-parameter Insert.  Then we'd have:
+
+procedure Replace
+  (Container : in out Set;
+   New_Item  : in     Element_Type;
+   Position  : in out Cursor;
+   Replaced  :    out Boolean);
+
+If New_Item is equivalent to the element designated by Position, then we
+assign New_Item to the element, and return the value True for Replaced.
+
+If New_Item is not equivalent to the element, then we delete the node
+designated by Position, and attempt to insert New_Item.
+
+If New_Item is equivalent to some other, already-existing element, then
+insertion fails.  So Position is set to the matching node, and Replaced is
+set to False.  In this case, the cardinality of the set has changed.
+
+If New_Item is not equivalent to another element, then the insertion
+succeeds.  So Position is set to the newly inserted node, and Replaced is
+set to True.
+
+In both cases when Replaced has the value True, then New_Item is in the set,
+and Position designates its node.  The difference between the two cases is
+that Position designates an already-existing node, or a newly-inserted node.
+The cardinality doesn't change.
+
+In the case when Replaced is False, it's because we deleted the node, but
+were unable to insert New_Item in the set.  The cardinality also changed.
+
+How does that sound?
+
+ENDMJH.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Friday, April 21, 2005  4:21 AM
+
+> Should the Position parameter have mode inout?  If By isn't 
+> equivalent to the element designated by Position, then the 
+> node is deallocated, which would leave Position with a 
+> dangling reference.
+
+I don't see this.  The wording says that the element is removed, not that
+the node is deallocated (node being essentially in implementation notion).
+
+I haven't looked at your implementation, but I would assume that the node
+contain (1) a bunch of pointers and other data useful for maintaining the
+set efficiently; and (2) the element value (in the definite case) or a
+pointer to the element value (in the indefinite case).
+
+In the definite case, the new element should just be stored in the node.
+In the indefinite case the element should be deallocated and the new value
+reallocated, and its pointer stored in the node.  In neither case should
+the node be deallocated.  Of course, the node may need to be moved to
+another location in the hash table/binary tree/whatever, but that's done
+by moving pointers, not by allocation/deallocation.
+
+So I don't think that the cursor can become invalid as part of this
+operation.
+
+> Furthermore, if the insertion fails, then the cardinality of 
+> the set would have changed, since that node would have been 
+> deleted from the set.  Yet the set is passed using in-mode, 
+> so really we have no way of doing what is even specified 
+> here.  I thought the point of passing the container as a 
+> parameter was because Replace_Element was like an optimized 
+> Delete followed by Insert, both of which change cardinality.
+
+In the scheme that I outlined above, the cardinality doesn't change.  I'd
+say if Storage_Error is raised by the allocation of the new element (in
+the indefinite case) then the container should not be affected, and at any
+rate I cannot get too excited about S_E.  If an exception is raised during
+assignment of the element (e.g. because the element is a controlled type)
+then it's harder to decide what to do, but note that this can happen with
+Replace, too.
+
+I think that it would be good to have a blanket statement somewhere
+explaining what happens when the assignment of elements raises an
+exception.  Other than that, I don't see the need to change this
+operation.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 22, 2005  7:49 AM
+
+> So I don't think that the cursor can become invalid as part 
+> of this operation.
+
+It depends on how you define "invalid," I guess.  You are correct that the
+node isn't deallocated, but it *is* removed from the underlying data
+structure, and then the insertion is attempted.  What should happen if the
+insertion fails?  
+
+Do you want to re-insert the node back into the data structure using its
+original value?  You certainly don't say anything about that in the
+descrption above.  All you say is that if the insertion fails, then P_E is
+raised.
+
+If you do want to reinsert the node (with its orignal value preserved), then
+why raise P_E?  The container isn't broken; in fact, it has the same state
+that it had prior to the call.  The closest analog is the 2-parameter
+Insert, and in that case we simply raise C_E.  
+
+ 
+> In the scheme that I outlined above, the cardinality doesn't 
+> change.  
+
+You have not stated what happens when the original element is removed from
+the container (which of course *does* change the cardinality), and when the
+insertion attempt with the new element fails.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Sunday, April 24, 2005  7:57 AM
+
+> I don't see this.  The wording says that the element is 
+> removed, not that the node is deallocated (node being 
+> essentially in implementation notion).
+
+Of course this assumes, in the unique case of Replace_Element and friends,
+that the implementation can remove the element from the internal data
+structure, and then not deallocate it, so that the same storage can be used
+again.
+
+You're sure this isn't overly constraining implementation choices?
+
+ 
+> I haven't looked at your implementation, but I would assume 
+> that the node contain (1) a bunch of pointers and other data 
+> useful for maintaining the set efficiently; and (2) the 
+> element value (in the definite case) or a pointer to the 
+> element value (in the indefinite case).
+
+The reference implementation implements the ordered set using a red-black
+tree.  You can see the implementation yourself here:
+
+
+<http://charles.tigris.org/source/browse/charles/src/ai302/a-coorse.adb?rev=
+1.23&sortby=date&view=markup>
+
+
+Look for a local procedure declared like this:
+
+procedure Replace_Element (Tree : in out Tree_Type;
+                           Node : in     Node_Access;
+                           Item : in     Element_Type) is
+begin
+
+   if Item < Node.Element
+     or else Node.Element < Item
+   then
+      null;
+   else
+       Node.Element := Item;
+       return;
+   end if;
+
+   -- lots of horrible junk goes here
+
+end Replace_Element;
+
+
+The hashed set is here:
+
+<http://charles.tigris.org/source/browse/charles/src/ai302/a-cohase.adb?rev=
+1.22&sortby=date&view=markup>
+
+
+Look for a local procedure declared like this:
+
+procedure Replace_Element (HT      : in out Hash_Table_Type;
+                           Node    : in     Node_Access;
+                           Element : in     Element_Type) is
+begin
+
+   if Equivalent_Elements (Node.Element, Element) then
+      Node.Element := Element;
+      return;
+   end if;
+
+   -- lots of horrible junk goes here
+
+end Replace_Element;
+
+
+If this operation had more modest aims, such as only having to replace an
+element in the same equivalence class, then the operation would be simple.
+(We could also get rid of that pesky extra parameter for the container.)
+
+But as it stands now, having to handle the fact that the new element is not
+in the same equivalence class as the old element is what makes this
+operation confusing, error-prone, difficult to implement, and hard to
+specify (especially when you throw in all the failure corner cases).
+ 
+
+> In the definite case, the new element should just be stored 
+> in the node. In the indefinite case the element should be 
+> deallocated and the new value reallocated, and its pointer 
+> stored in the node.  In neither case should the node be 
+> deallocated.  Of course, the node may need to be moved to 
+> another location in the hash table/binary tree/whatever, but 
+> that's done by moving pointers, not by allocation/deallocation.
+
+OK, I see your point about not having to make the parameters have inout
+mode.  But I'm still skeptical about the semantics, since I'm not sure that
+we're not stepping on the toes of implementers.
+
+ 
+> I think that it would be good to have a blanket statement 
+> somewhere explaining what happens when the assignment of 
+> elements raises an exception.  Other than that, I don't see 
+> the need to change this operation.
+
+How about a compromise.  As I mention above, the problem with this operation
+is that it attempts to do too much, by allowing the new element to have a
+different equivalence class than the old element. 
+
+The change I'm asking for would change the semantics such that the new
+element must belong to the same equivalence class as the old element.
+
+If the user attempts to pass in a new element with a different equivalence
+class, then just raise Constraint_Error.  
+
+This change in semantics means we can simplify the signature of
+Replace_Element so that it only has to pass the cursor and the element.  It
+would not have to pass the container, which (besides just being better and
+simpler) would make it identical to the Replace_Element operation for every
+other container.
+
+We give the user lots of functions to test the equivalence class of an
+element.  If a user wants to change the equivalence class of an element, he
+can do it the old fashioned way: just delete the old element and then insert
+the new element.  This is what Replace_Element attempts to do now, but with
+all the concomitant semantic headaches.  
+
+I humbly beseech thee to change the semantics (and signature) of
+Replace_Element for sets.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Monday, April 25, 2005  2:46 AM
+
+> Of course this assumes, in the unique case of Replace_Element 
+> and friends, that the implementation can remove the element 
+> from the internal data structure, and then not deallocate it, 
+> so that the same storage can be used again.
+> 
+> You're sure this isn't overly constraining implementation choices?
+
+Well, the specification of these packages has to make some number of
+assumptions, and surely these assumptions constrain the implementation.
+However, this particular assumption doesn't seem unreasonable to me, and
+it doesn't appear to cause trouble in your implementation.
+
+> But as it stands now, having to handle the fact that the new 
+> element is not in the same equivalence class as the old 
+> element is what makes this operation confusing, error-prone, 
+> difficult to implement, and hard to specify (especially when 
+> you throw in all the failure corner cases).
+
+Hey, you knew it was hard when you took the job! ;-)
+
+I am not too concerned about the error cases (other than the fact that
+things should be well specified).  If you get a Storage_Error, or if the
+assignment operation fails (in the case of an element which is of a
+controlled type) all bets are off anyway.  I think however that, for this
+operation to be useful, the user has to be able to assume that in the
+absence of an exception the element has actually been replaced and the
+container properly reordered/rehash.  Having to handle an exception to do
+a deletion/insertion would lead to horrible code in the clients, and
+that's not acceptable to me.
+
+> of Replace_Element so that it only has to pass the cursor and 
+> the element.  It would not have to pass the container, which 
+> (besides just being better and
+> simpler) would make it identical to the Replace_Element 
+> operation for every other container.
+> 
+> I humbly beseech thee to change the semantics (and signature) 
+> of Replace_Element for sets.
+
+I must say that I am quite puzzled by the profile of Replace_Element for
+sets, since, as you point out, it is different from all the other
+Replace_Elements.  I believe that this needs fixing (by removing the
+Container parameter; the Cursor is sufficient to determine the container
+anyway).  But I don't think that changing the semantics is a good idea.
+Yeah, it's going to cause a bit of trouble for the implementers, but yawn,
+I'd rather do that than cause trouble for each and every user.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Saturday, April 23, 2005  7:37 AM
+
+Section A.18.7 (Sets) of the current AI-302 draft says:
+
+START OF QUOTE:
+
+procedure Delete (Container : in out Set;
+                  Position  : in out Cursor);
+
+If Position equals No_Element, Delete has no effect...
+
+END OF QUOTE.
+
+MJH:
+
+Is this correct?  Shouldn't Delete raise C_E if Position has the value
+No_Element?  
+
+The semantics of delete were changed in Atlanta, such that the cursor-based
+Delete always raises C_E if Position = No_Element.
+
+ENDMJH.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Monday, April 25, 2005  2:23 AM
+
+Agreed, this was the semantics agreed upon in Atlanta.  C_E should be
+raised in this case.  I suppose it's an oversight, and it should be fixed.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Saturday, April 23, 2005  8:16 AM
+
+In the AI-302 draft, Replace is always declared like this:
+
+   procedure Replace (Container : in out Map;
+                      Key       : in     Key_Type;
+                      New_Item  : in     Element_Type);
+
+
+MJH:
+
+I forget: why is the container parameter passed using inout mode instead of
+just in?  Replace doesn't change the cardinality.
+
+ENDMJH.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Monday, April 25, 2005  2:25 AM
+
+I guess I have never really understood the meaning of the modes for
+containers.  It seems that your interpretation is that the mode reflects
+the cardinality, and that seems to be obeyed quite consistently.  So I
+tend to agree that it should be "in" here.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, April 25, 2005  4:44 AM
+
+I think "replace" should be treated specially,
+because at least for indefinite containers, it can
+change the constraints of an element, even if
+the subtype is indefinite, whereas
+the other operations (like update_element and
+query_element) cannot change constraints under
+such circumstances.  I'm not sure whether that
+kind of behavior implies we should use "in out,"
+but it seems like it might.
+
+We have some kind of "fiddles with elements"
+notion, and if that matched "in out" that
+might be a useful indication.  But perhaps
+it is best to associate with "in out" with
+"fiddles with container", which is a separte
+notion, if I remember correctly.  In any case,
+it would seem to be nice to have a clear
+specification somewhere of the meaning of
+"in out" with respect to these other
+notions.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Monday, April 25, 2005  5:54 AM
+
+> In any case,
+> it would seem to be nice to have a clear
+> specification somewhere of the meaning of
+> "in out" with respect to these other
+> notions.
+
+Along the same lines, it would also be nice to know what is the meaning of
+":=" for containers.  Vector has an Assign operation, which would seem to
+imply that ":=" is actually assigning references (shallow assignment) not
+containers (deep assignment).  This is quite weird because "=" does a deep
+comparison.
+
+The other containers apparently don't have an Assign operation, which
+seems inconsistent, and surely doesn't clarify the meaning of ":=".  For
+all containers "=" seems to do a deep comparison, so that part at least is
+consistent.
+
+My feeling is that we have two reasonable options: either a container
+object is viewed as a mere reference, in which case ":=" and "=" should be
+shallow operations, and the parameters should all be of mode "in"; or a
+container object is viewed as "the real stuff", in which case ":=" and "="
+should be deep operations, and the parameters should be "in out" when the
+cardinality or contents are modified.
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Monday, April 25, 2005  6:59 AM
+
+Agreed. Moreover, I think a copy operation *is* useful: it is sometimes 
+convenient to be able to store the state of a container, and to restore 
+it later.
+
+This means that if ":=" is shallow, there must be a copy operation also. 
+OTOH, I don't see much value in being able to compare whether two 
+containers are the same object or not. Therefore, I support the deep ":=".
+
+****************************************************************
+
+From: Martin Krischik
+Sent: Monday, April 25, 2005  6:47 AM
+
+All container operations are performed on "Element_Type" and not on "access 
+Element_Type". The container clearly operates on objects - "the real stuff" 
+as you call it. "=" and ":=" should therefore be deep operations.
+
+Having said that: For ":=" one could use some form of "lazy copy" as an 
+optimisation option. But this would need to be transparent to the user of the 
+container.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Monday, April 25, 2005  8:47 AM
+
+I think the operation named "Replace" should only use in-mode, since it
+doesn't change the cardinality of the container.
+
+I was also asking about the set version of the operation named
+"Replace_Element".  Unlike for other containers, it passes the container as
+an additional parameter.  It looks like the container param shouldn't be
+there, since this operation doesn't change the cardinality of the container.
+(Although, it does manipulate the container.)
+
+However, I still don't like the semantics of "Replace_Element".  It doesn't
+buy you anything that Delete/Insert don't.
+
+It's not clear from your comment whether you would treat "Replace_Element"
+specially too, or only just "Replace".  It seems to me that these operations
+are inconsistent with each other.
+
+"Replace" must first search the for the element identified by the New_Item
+parameter, and if it's not found it raises C_E.  If it is found, this means
+that the new item and (old) element belong to the same equivalence class,
+and the new item value is assigned to the element.  Simple.
+
+"Replace_Element" has a cursor parameter, so there's no need to search for
+the old element.  But here is where the existing semantics are different
+from "Replace".  If the equivalence class of By is different from the
+element designated by the cursor, then it's not a simple matter of
+assignment anymore.
+
+You have to remove the element from the data structure (and in the ordered
+case, that means unlinking the node and rebalancing the tree), assign By to
+the node's element, and then *attempt* to re-insert the node back into the
+tree (and if it succeeds, that means rebalancing the tree, again).  
+
+If the insertion fails, you have to reinsert the *original* value of the
+element (so you have to either make a copy of the original element, or defer
+somehow the assignment to the node's element).
+
+"Replace_Element" was always intended as a simple O(1) operation to assign a
+new value to the element designated by the cursor.  But because of the
+semantics of Replace_Element for sets, it's much worse than O(1) if the
+equivalence class is different.
+
+I'm just asking whether the Replace_Element for sets has the semantics you
+really want.  Because in the unique case of sets, Replace_Element must
+manipulate the container itself, rather than simply fiddling with an
+element's value.
+
+> We have some kind of "fiddles with elements"
+> notion, and if that matched "in out" that
+> might be a useful indication.  But perhaps
+> it is best to associate with "in out" with
+> "fiddles with container", which is a separte
+> notion, if I remember correctly.  
+
+Yes, that was my intent, anyway.  Where the cardinality of the container can
+change, then use inout.  Otherwise, use in. 
+
+I think this means that Replace should accept the container as an in-mode
+param, instead of as an inout param.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Monday, April 25, 2005 10:06 AM
+
+Pascal Leroy wrote:
+> 
+> Along the same lines, it would also be nice to know what is the meaning of
+> ":=" for containers.  
+
+":=" is always by copy (that is, a deep copy).
+
+> Vector has an Assign operation, which would seem to
+> imply that ":=" is actually assigning references (shallow assignment) not
+> containers (deep assignment).  This is quite weird because "=" does a deep
+> comparison.
+
+Not quite.  Vector, because of its unique properties, has a special 
+Assign operation that optimizes (deep) copy.  That operation allows the 
+internal array to be reused across (deep copy) assignment.  (Actually, 
+you could make a similar argument for all containers, especially hash 
+tables.)
+
+> The other containers apparently don't have an Assign operation, which
+> seems inconsistent, and surely doesn't clarify the meaning of ":=".  For
+> all containers "=" seems to do a deep comparison, so that part at least is
+> consistent.
+
+Everything is deep copy.  The Assign operation for vectors doesn't 
+change the semantics of assignment: it's always a deep copy.
+
+> My feeling is that we have two reasonable options: either a 
+> container object is viewed as a mere reference, in which case
+> ":=" and "=" should be shallow operations,and the parameters
+> should all be of mode "in";
+
+There are no shallow operations.
+
+> or a
+> container object is viewed as "the real stuff", in which case ":=" and "="
+> should be deep operations, and the parameters should be "in out" when the
+> cardinality or contents are modified.
+
+Not quite.  ":=" and "=" are always deep operations.
+
+When the container has mode inout, it means *only* that the cardinality 
+of the container can change.
+
+If elements can change (say, during Iterate), then the container is 
+still passed using in-mode.  That's because changing just elements 
+doesn't change the cardinality of the container.
+
+There is of course an implied internal reference.  In fact, the Move 
+operation exists precisely to take advantage of this property.
+
+Changing the container, versus just changing elements, are orthogonal 
+operations.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Monday, April 25, 2005 10:44 AM
+
+> > Along the same lines, it would also be nice to know what is the 
+> > meaning of ":=" for containers.
+> 
+> ":=" is always by copy (that is, a deep copy).
+
+Fine, but I can't seem to read it in normative text.
+
+> Not quite.  Vector, because of its unique properties, has a special 
+> Assign operation that optimizes (deep) copy.  That operation allows the 
+> internal array to be reused across (deep copy) assignment. (Actually, 
+> you could make a similar argument for all containers, especially hash 
+> tables.)
+
+I see this as a minuscule optimization and probably not worth it (the
+expensive part is going to be the element copy, which you have to do
+anyway).  But at any rate, all containers should be consistent in that
+respect.
+
+> When the container has mode inout, it means *only* that the cardinality 
+> of the container can change.
+
+This is your interpretation, but I don't see why this is a useful notion.
+
+> Changing the container, versus just changing elements, are orthogonal 
+> operations.
+
+Certainly not!  For hashed and ordered containers, changing one element
+involves a change in the ordering of the elements in the container, which
+is visible through operations such as Iterate, Next, etc.  To me, this is
+as important (or even more important) than the cardinality of the
+container.
+
+I suppose I could live with Tuck's notion that "in out" corresponds to
+"tampering with elements".  But basing the mode on the cardinality looks
+rather bizarre to me.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Monday, April 25, 2005  9:46 AM
+
+> It's not clear from your comment whether you would treat "Replace_Element"
+> specially too, or only just "Replace".  It seems to me that these operations
+> are inconsistent with each other.
+
+Actually, on the drive to work I just realized something.  The semantics 
+of Replace_Element for sets are inconsistent with 
+Generic_Keys.Update_Element_Preserving_Key too.
+
+It used to be the case that if Update_Element_Preserving_Key detected 
+that the key had changed, then that operation would attempt to reinsert 
+the element (with its new key) back into the set.  However, Tucker (and 
+I think Pascal too) thought these semantics were ridiculous, and so they 
+were changed.  Update_Element now has more modest aims, such that if the 
+key changes, the element is forcibly removed from the set and P_E is 
+raised.  The API is not ambiguous about what happens when you attempt to 
+change the key: it practically shouts "don't do it!".
+
+(Indeed, Generic_Keys is designed precisely to be able to detect changes 
+in key during Update_Element_Preserving_Key.  In fact, that's why 
+Update_Element_Preserving_Key is inside that nested package.  And it was 
+given the long, ugly name "Update_Element_Preserving_Key" for the 
+express purpose of putting the fear of God into anyone who dared change 
+the element's key.  So changing the key is A Bad Thing To Do.)
+
+However, Replace_Element has all the semantics Tucker hated about 
+Update_Element, and then some.  In fact the container manipulation is 
+hidden behind the scenes, since we're saying we're not going to pass the 
+container as a parameter anymore.  And that friendly name practically 
+begs programmers to go ahead and change keys with gay abandon.
+
+The problem is that if you attempt to change the equivalence class, then 
+it's like a lottery when you try to insert the new value.  I don't see 
+why gambling should be illegal during Update_Element_Preserving_Key, but 
+perfectly acceptable during Replace_Element.
+
+The current semantics of Replace_Element for sets must be a mistake.  So 
+let's fix the mistake.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Monday, April 25, 2005 11:11 AM
+
+> This is your interpretation, but I don't see why this is a useful notion.
+
+Because that's the model.  It's always been the model.  That's how Move 
+works.
+
+> Certainly not!  For hashed and ordered containers, changing one element
+> involves a change in the ordering of the elements in the container, which
+> is visible through operations such as Iterate, Next, etc.  To me, this is
+> as important (or even more important) than the cardinality of the
+> container.
+
+Unless we're talking about Replace_Element for sets, there is no such 
+thing as "changing an element means changing the order."  When you want 
+to do that (that is, change the key), you have to remove the key and 
+then reinsert the element.
+
+(Replace_Element for sets is currently broken, since it doesn't work 
+this way.)
+
+> I suppose I could live with Tuck's notion that "in out" corresponds to
+> "tampering with elements".  But basing the mode on the cardinality looks
+> rather bizarre to me.
+
+But Tuck also said that you could interpret mode inout as meaning 
+"fiddles with container," which is *not* the same thing as "tampers with 
+elements."
+
+Mode inout for containers has *always* meant that the cardinality of the 
+container can change.  From the dawn of time mode inout has had this 
+interpretation.
+
+The problem with making container inout everywhere is that this will 
+penalize users who only want to read the container (that is, call 
+Query_Element).  You want to pass the container as inout mode during 
+Iterate, because of the mere potential to modify its elements?  Now 
+that's bizarre!
+
+****************************************************************
+
+From: Martin Krischik
+Sent: Monday, April 25, 2005 11:08 AM
+
+> I see this as a minuscule optimization and probably not worth it (the
+> expensive part is going to be the element copy, which you have to do
+> anyway).  But at any rate, all containers should be consistent in that
+> respect.
+
+But you could optimise element copy as well - especially for indefinite 
+variants - by using a lazy copy technique.
+
+The important part is how the container behaves to the outside.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Monday, April 25, 2005 12:37 PM
+
+> But you could optimise element copy as well - especially for indefinite 
+> variants - by using a lazy copy technique.
+> 
+> The important part is how the container behaves to the outside.
+
+This is silly.  No one is going to do this.  You'd have to keep a 
+reference count somewhere --probably a per-element reference count at 
+that-- and then you'd have to implement type Cursor as a controlled 
+type.  And if the "copy" of the container is given to another task, then 
+you'll have to throw in synchronization as well.
+
+Designing a container library while trying to imagine an infinite space 
+of implementation possibilities would make the problem intractable.  The 
+library is deliberately low-level, and for the most part what you think 
+a container does on the inside is what the container really does do on 
+the inside.  The fact that we have hashed vs. sorted containers, and 
+definite vs. indefinite containers, only confirms this.
+
+****************************************************************
+
+From: Ehud Lamm
+Sent: Tuesday, April 26, 2005  4:03 AM
+
+> Agreed. Moreover, I think a copy operation *is* useful: it is sometimes 
+> convenient to be able to store the state of a container, and to restore 
+> it later.
+
+I agree. The choice I'd make: Containers should be viewed as objects, copy
+and comparison should be deep, and the parameters be in/out. 
+If one wants to make shallow copies, one can simply use an access type which
+points to the container (say for performance reasons).
+
+I think the notion that in/out refers to cardinality is likely to be
+confusing, and := and = must be consistent with each other, for the same
+reason.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, April 26, 2005  3:32 AM
+
+> Designing a container library while trying to imagine an infinite space 
+> of implementation possibilities would make the problem intractable.  The 
+> library is deliberately low-level, and for the most part what you think 
+> a container does on the inside is what the container really does do on 
+> the inside.  The fact that we have hashed vs. sorted containers, and 
+> definite vs. indefinite containers, only confirms this.
+
+I fully agree with Matt here.  I'll add that the user must have some idea
+of the underlying implementation model, otherwise it's hard to know how to
+write code using the containers (is container assignment expensive or not?
+is element assignment expensive or not?).
+
+We are trying to avoid unnecessarily constraining implementations, but the
+clients must have some idea of what's going on behind the scenes.  For
+instance we do not specify if sets are implemented using AVL trees, B
+trees, skip lists, etc., but we specify that the interesting operations on
+sets must be logarithmic in the length of the set.
+
+A vector that would do lazy copying of elements would probably not comply
+with the implementation advice that says that "Vectors should be
+implemented similarly to an array" because some operations that are cheap
+for arrays might trigger an O(N) copy of the entire container (depending
+on the way you do lazy copying).
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, April 26, 2005  4:11 AM
+
+> The problem with making container inout everywhere is that this will 
+> penalize users who only want to read the container (that is, call 
+> Query_Element).  You want to pass the container as inout mode during 
+> Iterate, because of the mere potential to modify its elements?  Now 
+> that's bizarre!
+
+I don't really understand the argument about Query_Element, since it's not
+supposed to tamper with the elements anyway.  Regarding Iterate, since it
+can very well modify the elements of the containers, I have no problem
+with making the mode "in out".
+
+I guess I don't see how mode "in out" actually "penalizes" the user.  It's
+just means they need to pass a variable, what's the big deal?
+
+Ada has this construct called a *constant* which is supposed to be a
+read-only object.  If I declare a constant container, I would expect,
+well, its contents to remain constant.  Not so.  At the moment the
+following works:
+
+	V : constant Vector := ...;
+	procedure Mess_With_Element (E : in out Element_Type) is separate;
+
+	Update_Element (V, 42, Mess_With_Element'Access);
+
+I find this counter-intuitive, and it weakens the static checking done by
+the compiler for no good reason.
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Tuesday, April 26, 2005  4:35 AM
+
+I think this is a very good point, and should serve as a basis for this 
+discussion. What is a constant container?
+1) The container itself does not change, but its content may change
+2) Neither the container nor the content changes
+
+Note that a constant access value does not preclude the designated 
+object to change (unless it is an access-to-constant type). Should we 
+have constant_containers?
+
+As for myself, I feel very hesitant on these issues...
+
+****************************************************************
+
+From: Ed Schonberg
+Sent: Tuesday, April 26, 2005  7:08 AM
+
+I fully agree. Ada is distinguished by having clear value semantics for 
+composite objects, and it
+seems like a serious mistake to say that containers have partial 
+reference semantics.  Assignment has to mean deep copy as for arrays 
+(general agreement here), and assignment and equality must correspond.  
+Reasoning about containers becomes much harder if the modification of an 
+element is not considered a modification of the container. For that 
+reason, any operation that affect the contents of a container should 
+have an  IN OUT parameter. The definition of "constant container" should 
+be intuitive: it's a container whose contents are invariant!
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, April 26, 2005  8:06 AM
+
+On the other hand, we have these things called "files" and "tasks"
+which do not have this property.  For file objects, in-out
+is used when you might be opening or closing the file.
+For tasks, you never need in-out (not even to abort the task ;-).
+So I think it is OK to have a distinct meaning for "in-out"
+for a container, but we need to be very clear about what it means.
+Note that in many file systems, you don't need to have "write"
+privilege on a directory to update the files in it.  But you
+need "write" to add or remove files.
+
+****************************************************************
+
+From: Ed Schonberg
+Sent: Tuesday, April 26, 2005  8:20 AM
+
+> On the other hand, we have these things called "files" and "tasks"
+> which do not have this property.
+
+and neither of them have assignment or equality, so the problem does not arise.
+Tasks and limited types in general have a syntax that indicates their special role
+in the language. Containers are just standard packages with clever data structures
+in them. Giving them unusual semantics without a distinguishing syntax seems to
+violate some language design rule, (I'm not to sure which !).
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, April 26, 2005  8:26 AM
+
+> On the other hand, we have these things called "files" and 
+> "tasks" which do not have this property.  For file objects, 
+> in-out is used when you might be opening or closing the file. 
+> For tasks, you never need in-out (not even to abort the task 
+> ;-).
+
+And one could argue that this was a mistake, and blame Jean, as usual ;-)
+
+> So I think it is OK to have a distinct meaning for 
+> "in-out" for a container, but we need to be very clear about 
+> what it means. Note that in many file systems, you don't need 
+> to have "write" privilege on a directory to update the files 
+> in it.  But you need "write" to add or remove files.
+
+I find the analogy rather weak, because it's unlikely that this is going
+to be the first thing that jumps to mind when people start using
+containers.  I think that Ed's analogy with arrays is much more cogent,
+especially considering that in a number of cases users will be changing
+code that uses arrays so as to use containers instead.  I'm sure they will
+be bitten by the subtle semantic changes from value to reference.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, April 26, 2005  9:23 AM
+
+>> On the other hand, we have these things called "files" and "tasks"
+>> which do not have this property.
+> 
+> and neither of them have assignment or equality, so the problem does not 
+> arise.
+
+Good point.  The fact that containers are non-limited
+and have "deep" semantics on equality and assignment argues
+strongly for "deep" semantice on in-out mode.  In other words,
+you have convinced me...
+
+****************************************************************
+From: Matthew Heaney
+Sent: Tuesday, April 26, 2005  8:46 AM
+
+> I find this counter-intuitive, and it weakens the static 
+> checking done by the compiler for no good reason.
+
+First of all, the checks you guys added in Atlanta require that the
+container be modified behind the scenes.  Even a call to Query_Element
+temporarily changes the state of the object to indicate that a query is in
+progress, in order to prevent the user from calling an operation from inside
+Process.all that would change the element's value.  So we can immediately
+dismiss your static checks argument.
+
+Second of all, a vector is *not* an array.  An array is an array, and a
+vector is a vector.  (Geez, I'm beginning to sound like Ayn Rand.)  A vector
+is more like a pointer to an unconstrained array, that is expanded as
+necessary as elements are added.  Even if the object designated by the
+pointer changes, the pointer itself stays the same.  And that's the reason
+why containers are inout only when the cardinality changes.
+
+Third of all, this entire discussion about constant-ness vs. variable-ness
+(an issue we settled months ago) only distracts from the issue at hand,
+which is that replace_element has horrible semantics.
+
+Now, about the issue with being able to modify elements.  The problem is
+that neither the Ada language nor its standard container library have "const
+iterators" or "oonst operations" a la the STL.
+
+The example above could be written in C++ like this:
+
+  const vec_t v = ...;
+  v[42] = ...;
+
+This wouldn't compile in C++, since the index operator is overloaded like
+this:
+
+   const value_type& operator[](size_type) const;
+   value_type& operator[](size_type);
+
+For a const vector, the first operator will get invoked, and it returns a
+const reference.
+
+The iterators in the STL are similar.  The operations are:
+
+   const_iterator begin() const;
+   iterator begin();
+
+So when you say:
+
+   ... = v.begin();
+
+which begin() op gets invoked depends on the const-ness of vector v.  So if
+you said this:
+
+  void f(const vec_t& v)
+  {
+     vec_t::iterator i = v.begin();  //won't compile  
+  }
+
+This won't work, since the begin() that gets invoked returns type
+const_iterator.  You have to either do this:
+
+  void g(const vec_t& v)
+  {
+     vec_t::const_iterator i = v.begin();  //ok
+  }
+
+or this:
+
+  void h(vec_t& v)   //non-const reference
+  {
+      vec_t::iterator i = v.begin();
+      vec_t::const_iterator j = v.begin();  //works too
+  }
+
+Needless to say, Ada doesn't have anything like this.  To do something
+similar you'd have to have two kinds of cursors, something like:
+
+   type Cursor is private;
+   type Constant_Cursor is private;
+
+   procedure Update_Element
+     (Position : Cursor;
+      Process  : not null access proc...);
+
+   procedure Query_Element
+     (Position : Constant_Cursor;
+      Process  : not null access proc...);
+
+   function First (Container : Vector) return Cursor;
+   function First (Container : Vector) return Constant_Cursor;
+
+But this can't work since Ada doesn't use constant-ness of the object to
+determine which operation to invoke:
+
+  procedure Op (V : in Vector) is
+     C : Cursor := First (V);  -- compiles in Ada, not C++
+  begin
+     null;
+  end;
+
+
+The model now, and the model that has been in use since my original proposal
+over 18 months ago, is that the representation of a container type comprises
+basically two pieces of information: a pointer to some internal data
+structure, and the number of elements in the container.
+
+It has always been the case, from the beginning of time, that mode inout for
+containers means specifically that the cardinality of the container changes.
+Mode in for containers means that the cardinality does not change.  And
+that's all container mode means.
+
+Manipulation of elements (either querying or updating) has always, always
+been orthogonal to the issue of manipulation of containers.  This simply
+reflects the fact that it's impossible to do some things in Ada.  Yes, Ada
+has access types that indicate constant-ness, e.g.
+
+   type Element_Access is access all Element_Type;
+   type Element_Constant_Access is access constant Element_Type;
+
+but there's no way in Ada to give a Cursor type constant-ness a la an access
+type.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Tuesday, April 26, 2005  9:48 AM
+
+ed schonberg wrote:
+> The definition of "constant container" should
+> be intuitive: it's a container whose contents are invariant!
+
+declare
+    SA : constant String_Access := new String'("42");
+begin
+    SA.all := "Ed";
+end;
+
+We might want to distinguish between "logically invariant" and 
+"physically invariant," since some operations that are logically 
+constant must physically modify the container object.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, April 26, 2005  9:51 AM
+
+I believe to fully implement "deep" semantics, we would have
+to have two types of cursors, one which allows update,
+and one which doesn't.  We would also have to duplicate
+most operations that produce cursors, to associate the
+appropriate type with the appropriate container mode.
+In any case, I sympathize with the arguments on both sides of this
+issue.
+
+To answer Matt, I don't think we are concerned
+about "behind the scenes" modifications which might
+be required by "query," but rather with the higher
+level notion that after an operation is completed,
+is the container "equal" to its value before the
+operation.  If its value has changed at this high
+level, then there is an argument that the
+mode should be in-out.
+
+To answer the other side, there is no hard-and-fast rule
+that mode "in out" is required to change the value.
+We clearly know there are examples of data structures (I've used some)
+that provide "deep" assignment and "deep" equality,
+but which take advantage of internal levels of indirection
+to allow operations with mode "in" that effectively
+change the "value."
+
+Clearly there is a tradeoff here.  Realistically, we
+probably have to accept the current state of the
+proposal, or some minor "tweaks" to it.  A wholesale
+change at this stage seems unwise and impractical.  Most important is
+that we make it *very* clear what is the model, and try to be
+as consistent with that as possible.  Programmers can
+certainly adapt, so long as the model is clear.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, April 26, 2005  9:51 AM
+
+> First of all, the checks you guys added in Atlanta require 
+> that the container be modified behind the scenes.  Even a 
+> call to Query_Element temporarily changes the state of the 
+> object to indicate that a query is in progress, in order to 
+> prevent the user from calling an operation from inside 
+> Process.all that would change the element's value.  So we can 
+> immediately dismiss your static checks argument.
+
+Not so fast.  It has not escaped our notice that the container needs to be
+locked even when passed with mode "in", but we reasoned that this just
+means that the lock (and possibly other stuff) needs to be implemented
+with a level of indirection.  No big deal, what's going on behind the
+scenes is irrelevant to the user.  We are discussing constancy of the
+contents of the container, not some implementation detail as to how a
+particular check is implemented.
+
+> A vector is more like a pointer to an 
+> unconstrained array...
+
+Hmm, that doesn't seem to be what the author of the normative text
+thought, e.g. A.18.2(2/2): "A vector container behaves conceptually as an
+array that expands as necessary as items are inserted".  Note that it says
+"an array", not "a pointer to an array".
+
+> Third of all, this entire discussion about constant-ness vs. 
+> variable-ness (an issue we settled months ago) only distracts 
+> from the issue at hand, which is that replace_element has 
+> horrible semantics.
+
+These are two distinct issues, and both must be resolved.  But I must say
+that I am more interested by value/reference semantics than by what
+happens when Replace_Element raises Storage_Error.
+
+> It has always been the case, from the beginning of time, that 
+> mode inout for containers means specifically that the 
+> cardinality of the container changes. Mode in for containers 
+> means that the cardinality does not change.  And that's all 
+> container mode means.
+
+This may have been the case from the beginning of time, but it doesn't
+mean that it's right.  It just means that nobody noticed that this model
+led to oddities regarding the value/reference semantics of containers.  I
+don't want to bias the discussion, but I am starting to feel a
+quasi-consensus here, with one Matt Heaney the only dissenting voice (not
+the first time that this happens ;-).
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Tuesday, April 26, 2005  10:13 AM
+
+> I don't want to bias the discussion, but I am starting to feel a
+> quasi-consensus here, with one Matt Heaney the only dissenting voice 
+ > (not the first time that this happens ;-).
+
+Par for the course, as they say...
+
+****************************************************************
+
+From: Ed Schonberg
+Sent: Tuesday, April 26, 2005 10:15 AM
+
+>The model now, and the model that has been in use since my original proposal
+>over 18 months ago, is that the representation of a container type comprises
+>basically two pieces of information: a pointer to some internal data
+>structure, and the number of elements in the container.
+>
+>It has always been the case, from the beginning of time, that mode inout for
+>containers means specifically that the cardinality of the container changes.
+>Mode in for containers means that the cardinality does not change.  And
+>that's all container mode means.
+  
+This is what we are arguing about. There are good reasons to say that 
+any modification of the contents of the container requires that the 
+container be passed as an in-out parameter. Modifying an element IS a 
+modification of the contents. For something that is intended to 
+represent a set, for example, if S1 = S2
+before an operation that receives S1 as an IN parameter,  then it is 
+reasonable to expect that S1 = S2 after.
+
+>Manipulation of elements (either querying or updating) has always, always
+>been orthogonal to the issue of manipulation of containers. 
+
+"Always, always" sounds like a long time. This separation is 
+questionable. It may reflect some aspects of the implementation but it 
+is not necessarily the desired semantics. In fact, I don't understand this:
+a membership operation certainly manipulates the container AND queries 
+the elements. I certainly expect this operation to have an IN parameter 
+for the container. On the other hand, a piece of code
+that iterates over a container and multiplies all its elements by 7 
+better be in a context where the container is a variable. That seems to 
+me the consistent semantics.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Tuesday, April 26, 2005 10:30 AM
+
+> On the other hand, a piece of code
+> that iterates over a container and multiplies all its elements by 7 
+> better be in a context where the container is a variable. That seems to 
+> me the consistent semantics.
+
+But you can't do any of this without two different kinds of cursor 
+types.  And then you have to figure out a way to ensure that you're only 
+able to construct a read-only cursor when you have only a constant view 
+of the container, and a way to construct a read-only or read-write 
+cursor when you have a variable view of the container.
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, April 26, 2005 10:36 AM
+
+> Realistically, we
+> probably have to accept the current state of the
+> proposal, or some minor "tweaks" to it.
+
+If you look at the details of the current specification, you'll notice
+that the tweaks that would be required would indeed be minor, assuming
+that we don't get into the business of having read-only and read-write
+cursors.
+
+At the moment, many of the operations that change the contents of the
+containers do have mode "in out", because they can cause cardinality
+changes under some circumstances.  The only operations that would need to
+be modified (as far as I can tell, but I may have missed some) are Swap,
+Update_Element, Iterate and Reverse_Iterate.  And probably the infamous
+Replace_Element.
+
+On the other hand one could argue that Reserve_Capacity doesn't change the
+logical properties of the container (in particular, "=") so its argument
+might be of mode "in".  But I don't have strong feelings about this one.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, April 26, 2005 10:48 AM
+
+> At the moment, many of the operations that change the contents of the
+> containers do have mode "in out", because they can cause cardinality
+> changes under some circumstances.  The only operations that would need to
+> be modified (as far as I can tell, but I may have missed some) are Swap,
+> Update_Element, Iterate and Reverse_Iterate.  And probably the infamous
+> Replace_Element.
+
+I would certainly argue for a version of Iterate and Reverse_Iterate
+that take "in" mode.  That seems quite important.
+That might mean, however, that we need to have two types
+of cursors.  That feels like more than a "tweak."  Perhaps
+Iterate and Reverse_Iterate would remain mode "in" for practical
+reasons, but with appropriate visible warnings that updates
+might be performed indirectly on individual elements.
+
+> On the other hand one could argue that Reserve_Capacity doesn't change the
+> logical properties of the container (in particular, "=") so its argument
+> might be of mode "in".  But I don't have strong feelings about this one.
+
+The only reason to call Reserve_Capacity is because you are about
+to add elements, so there seems no reason to make this mode "in,"
+and it would unnecessarily complicate implementation to not
+be able to write on the "direct" object when increasing the capacity.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, April 2, 2005 11:20 AM
+
+You can ignore this response.  I was confused.
+The key thing is that Iterate and Reverse_Iterate
+(and many functions) provide cursors, but you
+normally have to provide an extra "container"
+parameter when you want to use the cursor.
+The debate is whether Update_Element and
+Replace_Element should require this extra parameter,
+and what should be its mode (presumably in-out).
+
+****************************************************************
+
+From: Ed Schonberg
+Sent: Tuesday, April 26, 2005 10:49 AM
+
+> But you can't do any of this without two different kinds of cursor 
+> types.  And then you have to figure out a way to ensure that you're 
+> only able to construct a read-only cursor when you have only a 
+> constant view of the container, and a way to construct a read-only or 
+> read-write cursor when you have a variable view of the container.
+
+I'm not asking for anything this elaborate (or C++-ish). The membership 
+example I mentioned does not expose the cursor, so the problem does not 
+arise. The manipulation of a container with an explicit cursor should 
+always be on a variable view of the container.  This way there is no 
+possibility of lying.
+we may lose a little precision on constantness, but nothing will be 
+misleading.  So I see no use for a read-only cursor. If you want search 
+primitives that return a cursor, it's reasonable to assume that this is 
+for purposes of subsequent modification of the (contents of) the 
+container, and this should be a read-write cursor, in your terminology.
+
+****************************************************************
+
+From: Jean-Pierre Rosen
+Sent: Tuesday, April 26, 2005 11:10 AM
+
+> The only reason to call Reserve_Capacity is because you are about
+> to add elements, so there seems no reason to make this mode "in,"
+> and it would unnecessarily complicate implementation to not
+> be able to write on the "direct" object when increasing the capacity.
+> 
+I agree with Ed's razor that if S1=S2 before calling a procedure with an 
+"in" parameter, users would expect that S1=S2 after.
+
+OTOH, I'm not worried if S1=S2 before calling a procedure with an "in 
+out" parameter, and it still holds after...
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, April 26, 2005 11:18 AM
+
+> ... So I see no use for a read-only cursor. If you want search 
+> primitives that return a cursor, it's reasonable to assume that this is 
+> for purposes of subsequent modification of the (contents of) the 
+> container, and this should be a read-write cursor, in your terminology.
+
+I think you should look at the interface.  I was also confused,
+because I still mix up the distinction between a cursor and
+an "active iterator".
+
+Iterate and Reverse_Iterate provide cursors, but there are also
+many *functions* that return cursors.  The key thing is that
+most of the operations that use cursors to update something
+in a container, *also* take the container itself as a parameter,
+so the operation that produces the cursor is irrelevant.
+
+The exceptions are "Update_Element" and "Replace_Element."
+It seems like what we are really debating is whether Update_Element
+and Replace_Element should also require a container
+parameter, and what should be the mode of that parameter.
+It seems relatively straightforward to require a mode "in-out"
+container parameter for these, and that would satisfy almost
+all of the goals.  Only one type of cursor is required, you
+can iterate through a collection passed in read-only mode,
+etc.  But if and when you decide to modify an element, you
+have to provide the container itself as a read-write
+parameter, even if the underlying implementation doesn't
+need the parameter.  It is just a way to guarantee that
+the update is performed in a place where you have write
+"permission."
+
+****************************************************************
+
+From: Bob Duff
+Sent: Tuesday, April 26, 2005 11:30 AM
+
+Seems to me something is wrong if we're doing this kind of major
+redesign work at this point!
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Tuesday, April 26, 2005 11:47 AM
+
+I think "tweaking" is more like it.  As Tucker pointed out, you could 
+pass the container as an additional, in-out parameter to Update_Element 
+and Replace_Element, and then all would be well.
+
+****************************************************************
+
+From: Alexander E. Kopilovich
+Sent: Tuesday, April 26, 2005 12:24 PM
+
+>Note that in many file systems, you don't need to have "write"
+>privilege on a directory to update the files in it.  But you
+>need "write" to add or remove files.
+
+So actually there are two different kinds of containers: one is "protected"
+container, which cares for (deep) contents of its elements, while another is
+just a bundle, which does not interfere with individual behaviour of its
+elements.
+  Those directories, which you mentioned, are an example of that second kind
+of containers. 
+  It is really interesting, what will be decided about that for Ada.Containers
+- there are only 4 options:
+
+1) choose first kind ("protected")
+2) choose second kind ("bundle")
+3) provide both kinds of containers
+4) mix both kinds in some convoluted way.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, April 26, 2005 12:44 PM
+
+Bob Duff wrote:
+
+> Seems to me something is wrong if we're doing this kind of major
+> redesign work at this point!
+
+I agree in general.
+
+But this issue has come up virtually every time that the containers have
+been discussed, and Matt (and to a lesser extent, I) have always said that
+there was a clear design principle. And usually the person that wanted
+change was talked out of it.
+
+But perhaps that was the wrong response to the question. Now that we do have
+a clear notion of container modification, perhaps it would be better to use
+that for determining the parameter mode. The usual argument against
+requiring "in-out" everywhere is that it doesn't work in functions. As long
+as functions are *only* used for queries (and there are no call-back
+functions), in-out for any modifications seems to work. (It doesn't work
+well in Claw, but the problem there is call-back functions that the user has
+to write.)
+
+****************************************************************
+
+From: Jeffrey Carter
+Sent: Tuesday, April 26, 2005 11:35 PM
+
+> I agree. The choice I'd make: Containers should be viewed as objects, copy
+> and comparison should be deep, and the parameters be in/out. 
+> If one wants to make shallow copies, one can simply use an access type which
+> points to the container (say for performance reasons).
+
+Predefined ":=" has always had value semantics in Ada. I think it would 
+be a big mistake to have the containers be different in that regard. 
+After assignment, the 2 containers should be separate objects with equal 
+contents.
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
+
+****************************************************************
+
+From: Matthew Heaney
+Sent: Friday, April 2, 2005  9:31 AM
 
 ****************************************************************
 

Questions? Ask the ACAA Technical Agent