CVS difference for ais/ai-20302.txt

Differences between 1.13 and version 1.14
Log of other versions for file ais/ai-20302.txt

--- ais/ai-20302.txt	2004/12/09 19:55:41	1.13
+++ ais/ai-20302.txt	2005/01/07 03:05:14	1.14
@@ -1,4 +1,4 @@
-!standard A.18 (00)                                  04-11-01  AI95-00302-03/08
+!standard A.18 (00)                                  04-12-30  AI95-00302-03/09
 !standard A.18.1 (00)
 !standard A.18.2 (00)
 !standard A.18.3 (00)
@@ -17,6 +17,8 @@
 !standard A.18.16 (00)
 !standard A.4.9 (00)
 !class amendment 04-01-14
+!status Amendment 200Y 04-12-31
+!status ARG Approved 10-0-0  04-11-20
 !status work item 04-01-14
 !status received 04-01-14
 !priority Medium
@@ -34,7 +36,7 @@
 
 !problem
 
-If is often the case that the solution to a programming problem requires
+It is often the case that the solution to a programming problem requires
 a collection of elements. The Ada language of course provides a
 built-in array type, but typical problems often require a data structure
 with better time behavior or more sophisticated semantics. Even if you
@@ -123,9 +125,18 @@
 before which it is guaranteed that no automatic hash table resizing occurs),
 thus preserving constant time complexity for insertions.
 
-The set associative container maintains elements in sort order. Insertions
-and searches have O(log N) time complexity even in the worst case.
+The ordered map associative containers maintains the keys in sort order.
+Insertions and searches have O(log N) time complexity even inthe worst case.
 
+The hashed set associative containers scatter elements in the container
+according to a hash function. The size of the hash table is automatically
+increased when the length of the container equals its capacity (which specifies
+the length before which it is guaranteed that no automatic hash table resizing
+occurs), thus preserving constant time complexity for insertions.
+
+The ordered set associative container maintains elements in sort order.
+Insertions and searches have O(log N) time complexity even in the worst case.
+
 All of the containers have alternate forms that accept an element type that is
 indefinite. The indefinite hashed maps also accept an indefinite key type,
 allowing (for example) type String to be used as the generic actual key type.
@@ -149,6 +160,9 @@
 section that illustrates the kinds of problems the library solves, and
 the most effective way to use the library to solve them.
 
+This AI makes use of anonymous access-to-subprogram types, and therefore
+assumes that AI-254 will be part of the Amendment.
+
 !wording
 
 Add Ada.Strings.Hash and Ada.Strings.Unbounded.Hash to A.4.7(29).
@@ -160,7 +174,7 @@
 
 Static Semantics
 
-The following library-level subprograms are defined:
+The library function Strings.Hash has the following declaration:
 
 with Ada.Containers;
 function Ada.Strings.Hash (Key : String) return Containers.Hash_Type;
@@ -169,6 +183,8 @@
 Return an implementation-defined value which is a function of the value of Key.
 If A and B are strings such that A equals B, Hash(A) equals Hash(B).
 
+The library function Strings.Unbounded.Hash has the following declaration:
+
 with Ada.Containers;
 function Ada.Strings.Unbounded.Hash (Key : Unbounded_String) return
     Containers.Hash_Type;
@@ -226,9 +242,12 @@
 The following major non-limited containers are provided:
    * (Expandable) Vectors of any non-limited type;
    * Doubly-linked Lists of any non-limited type;
-   * Hashed Maps keyed by any non-limited type containing any
-non-limited type;
-   * Ordered Sets of any non-limited type.
+   * Hashed Maps keyed by any non-limited hashable type, and containing any non-
+limited type;
+   * Ordered Maps keyed by any non-limited ordered type, and containing any non-
+limited type;
+   * Hashed Sets of any non-limited hashable type;
+   * Ordered Sets of any non-limited ordered type.
 
 Separate versions for definite and indefinite element types are provided, as
 those for definite types can be implemented more efficiently.
@@ -252,22 +271,22 @@
 to exist between executions of a program) and so on.
 
 Note that the language already includes several requirements that are
-important to the use of containers. First, library packages must be
-reentrant - multiple tasks can use the packages as long as they operate on
-separate containers. Thus, it is only necessary for a user to protect a
-container if a single container needs to be used by multiple tasks.
-
-Second, the language requires that language-defined types stream "properly".
-That means that the stream attributes can be used to implement persistence
-of containers when necessary, and containers can be passed between
-partitions of a program.
-
-Finally, the language requires that equality of language-defined types
-compose "properly". This means that the version of "=" directly used by
-users is the same one that will be used in generics and in predefined equality
-operators of types with components of the containers and/or cursors. This
-prevents the abstraction from breaking unexpectedly.
+important to the use of containers. These requirements include:
 
+* Library packages must be reentrant - multiple tasks can use the packages as
+  long as they operate on separate containers. Thus, it is only necessary for a
+  user to protect a container if a single container needs to be used by
+  multiple tasks.
+
+* Language-defined types stream must "properly". That means that the stream
+  attributes can be used to implement persistence of containers when necessary,
+  and containers can be passed between partitions of a program.
+
+* Equality of language-defined types must compose "properly". This means that
+  the version of "=" directly used by users is the same one that will be used
+  in generics and in predefined equality operators of types with components of
+  the containers and/or cursors. This prevents the abstraction from breaking
+  unexpectedly.
 
 If a container's element type is controlled, the point at which the element
 is finalized will depend on the implementation of the container. We do not
@@ -291,6 +310,7 @@
 as AI-179 puts it, so we don't try to specify what happens in that case.
 The implementation should propagate the exception.
 
+Implementation Notes
 
 It is expected that exceptions propagated from these operations do not
 damage containers. That is, if Storage_Error is propagated because of an
@@ -324,9 +344,9 @@
 The library package Containers has the following declaration:
 
 package Ada.Containers is
-   pragma Pure;
+   pragma Pure(Containers);
 
-   type Hash_Type is mod <Implementation-Defined>;
+   type Hash_Type is mod <implementation-defined>;
 
    type Count_Type is range 0 .. <implementation-defined>;
 
@@ -335,6 +355,8 @@
 Hash_Type represents the range of the result of a hash function. Count_Type
 represents the (potential or actual) number of elements of a container.
 
+Each child unit of Containers defines a container type.
+
 Implementation Advice
 
 Hash_Type'Modulus should be at least 2**32. Count_Type'Last should be at least
@@ -346,17 +368,17 @@
 
 A.18.2 The Package Containers.Vectors
 
-The language-defined package Containers.Vectors provides a private type Vector
-and a set of operations. A vector container allows insertion and deletion at
-any position, but it is specifically optimized for insertion and deletion at
-the high end (the end with the higher index) of the container. A vector
-container also provides random access to its elements.
-
-A vector container object manages an unconstrained internal array, which
-expands as necessary as items are inserted. The *length* of a vector is
-the number of elements that the vector contains. The *capacity* of a vector
-corresponds to the number of elements that can be stored in the internal array,
-and will always be no less than the length of the vector.
+The language-defined generic package Containers.Vectors provides private types Vector
+and Cursor, and a set of operations for each type. A vector container allows
+insertion and deletion at any position, but it is specifically optimized for
+insertion and deletion at the high end (the end with the higher index) of the
+container. A vector container also provides random access to its elements.
+
+A vector container behaves conceptually as an array that expands as necessary
+as items are inserted. The *length* of a vector is the number of elements that
+the vector contains. The *capacity* of a vector is the maximum number of
+elements that can be inserted into the vector prior to it being automatically
+expanded.
 
 A vector container may contain *empty elements*. Empty elements do not have a
 specified value.
@@ -374,23 +396,20 @@
 
 Static Semantics
 
-The library package Containers.Vectors has the following declaration:
+The generic library package Containers.Vectors has the following declaration:
 
 generic
-
    type Index_Type is range <>;
-
    type Element_Type is private;
-
    with function "=" (Left, Right : Element_Type)
       return Boolean is <>;
-
 package Ada.Containers.Vectors is
-   pragma Preelaborate (Vectors);
+   pragma Preelaborate(Vectors);
 
    subtype Extended_Index is
-      Index_Type'Base range Index_Type'First-1 .. Index_Type'Last +
-          Boolean'Pos (Index_Type'Base'Last > Index_Type'Last);
+      Index_Type'Base range
+         Index_Type'First-1 ..
+         Index_Type'Min (Index_Type'Base'Last - 1, Index_Type'Last) + 1;
    No_Index : constant Extended_Index := Extended_Index'First;
 
    subtype Index_Subtype is Index_Type;
@@ -444,22 +463,22 @@
    function Element (Position : Cursor) return Element_Type;
 
    procedure Query_Element
-       (Container : in Vector;
-        Index     : in Index_Type;
-        Process   : not null access procedure (Element : in Element_Type));
+     (Container : in Vector;
+      Index     : in Index_Type;
+      Process   : not null access procedure (Element : in Element_Type));
 
    procedure Query_Element
-       (Position : in Cursor;
-        Process  : not null access procedure (Element : in Element_Type));
+     (Position : in Cursor;
+      Process  : not null access procedure (Element : in Element_Type));
 
    procedure Update_Element
-       (Container : in Vector;
-        Index     : in Index_Type;
-        Process   : not null access procedure (Element : in out Element_Type));
+     (Container : in Vector;
+      Index     : in Index_Type;
+      Process   : not null access procedure (Element : in out Element_Type));
 
    procedure Update_Element
-       (Position : in Cursor;
-        Process : not null access procedure (Element : in out Element_Type));
+     (Position : in Cursor;
+      Process  : not null access procedure (Element : in out Element_Type));
 
    procedure Replace_Element (Container : in Vector;
                               Index     : in Index_Type;
@@ -602,12 +621,12 @@
    function Has_Element (Position : Cursor) return Boolean;
 
    procedure  Iterate
-       (Container : in Vector;
-        Process : not null access procedure (Position : in Cursor));
+     (Container : in Vector;
+      Process   : not null access procedure (Position : in Cursor));
 
    procedure Reverse_Iterate
-       (Container : in Vector;
-        Process : not null access procedure (Position : in Cursor));
+     (Container : in Vector;
+      Process   : not null access procedure (Position : in Cursor));
 
 private
 
@@ -616,93 +635,114 @@
 end Ada.Containers.Vectors;
 
 
-The type Vector needs finalization (see 7.6).
+The type Vector is used to represent vectors. The type Vector needs finalization
+(see 7.6).
 
-Empty_Vector represents the empty vector container. It has a length of 0. If an
-object of type Vector is not otherwise initialized, it will be initialized to
-the same value as Empty_Vector.
+Empty_Vector represents the empty vector object. It has a length of 0. If an
+object of type Vector is not otherwise initialized, it is initialized to the
+same value as Empty_Vector.
 
 No_Element represents a cursor that designates no element. If an object of type
-Cursor is not otherwise initialized, it will be initialized to the same
-value as No_Element.
+Cursor is not otherwise initialized, it is initialized to the same value as
+No_Element.
 
-No_Index represents a position that does not correspond to any element.
-The subtype Extended_Index includes the indices covered by Index_Type
-plus the value No_Index and, if it exists, the successor to the
-Index_Type'Last.
+No_Index represents a position that does not correspond to any element. The
+subtype Extended_Index includes the indices covered by Index_Type plus the
+value No_Index and, if it exists, the successor to the Index_Type'Last.
 
 AARM Note: We require the existence of Index_Type'First - 1, so that No_Index
 and Last_Index of an empty vector is well-defined. We don't require the
 existence of Index_Type'Last + 1, as it is only used as the position of
 insertions (and needs to be allowed only when inserting an empty vector).
 
-function To_Vector (Length : Count_Type) return Vector;
+Some operations are assumed to work on a constant set of elements. For such
+an operation, a subprogram is said to *tamper with cursors* of a vector
+object V if:
+
+ * it inserts or deletes elements of V, that is, it calls the Insert,
+   Insert_Space, Clear, Delete, Delete_Last, or Set_Length procedures with V
+   as a parameter; or
+
+   AARM To Be Honest: Operations which are defined to be equivalent to
+   a call on one of these operations also are included. Similarly, operations
+   which call one of these as part of their definition are included.
+
+ * it finalizes V; or
+ * it calls the Move procedure with V as a parameter.
+
+Some operations are assumed to not change elements. For such an operation, a
+subprogram is said to *tamper with elements* of a vector object V if:
+
+   * it tampers with cursors of V; or
+   * it modifies one or more elements of V, that is, it calls the
+     Replace_Element, Update_Element, or Swap procedures or an
+     instance of Generic_Sort with V as a parameter.
+
+   AARM Note:
+   Swap and Generic_Sort copy elements rather than reordering them, so
+   they can be allowed for Iterate.
 
-Returns a vector with a length of Length. The vector is filled with empty
-elements.
+function To_Vector (Length : Count_Type) return Vector;
 
+Returns a vector with a length of Length, filled with empty elements.
 
 function To_Vector
   (New_Item : Element_Type;
    Length   : Count_Type) return Vector;
-
-Returns a vector with a length of Length, and elements initialized to the
-value New_Item.
 
+Returns a vector with a length of Length, filled with elements initialized to
+the value New_Item.
 
 function "&" (Left, Right : Vector) return Vector;
 
-Returns a vector comprising the elements of Right appended in their
-original order to the vector Left.
+Returns a vector comprising the elements of Left followed by the elements of
+Right.
 
 function "&" (Left  : Vector;
               Right : Element_Type) return Vector;
 
-Returns a vector comprising the element Right appended to the vector Left.
+Returns a vector comprising the elements of Left followed by the element Right.
 
 function "&" (Left  : Element_Type;
               Right : Vector) return Vector;
 
-Returns a vector comprising the element Left prepended to the vector Right.
+Returns a vector comprising the element Left followed by the elements of Right.
 
 function "&" (Left, Right  : Element_Type) return Vector;
 
 Returns a vector comprising the element Left followed by the element Right.
 
-
 function "=" (Left, Right : Vector) return Boolean;
-
-If Left denotes the same object as Right, then this function returns
-True. Otherwise if Left and Right have different lengths, then this
-function returns False. Otherwise, it compares each element in Left to
-the corresponding element in Right using the generic formal equality
-operator. If element equality returns False, then this function returns
-False; otherwise, this function returns True. Any exception raised
-during evaluation of element equality is propagated.
 
+If Left and Right denote the same vector object, then the function returns
+True. If Left and Right have different lengths, then the function returns
+False. Otherwise, it compares each element in Left to the corresponding element
+in Right using the generic formal equality operator; if element equality
+returns False, then the function returns False. If the function has not
+returned a result after checking all of the elements, it returns True. Any
+exception raised during evaluation of element equality is propagated.
 
 function Capacity (Container : Vector) return Count_Type;
 
-Returns the length of the internal array.
-
+Returns the capacity of Container.
 
 procedure Reserve_Capacity (Container : in out Vector;
                             Capacity  : in     Count_Type);
 
-Reserve_Capacity sets the capacity of Container to a value which is at least the
-value Capacity and which is greater than the length of Container, expanding (or
-contracting) the internal array to hold at least Capacity elements. Expansion
-or contraction will require allocation, and possibly copying and deallocation
-of elements. Any exceptions raised by these operations are propagated, leaving
-the container with at least the original length and elements.
+Reserve_Capacity allocates new internal data structures such that the length of
+the resulting vector can become at least the value Capacity without requiring
+an additional call to Reserve_Capacity, and is large enough to hold the current
+length of Container. Reserve_Capacity then copies the elements into the new
+data structures and deallocates the old data structures. Any exception raised
+during allocation is propagated and Container is not modified.
 
 AARM Notes
 
 Expanding the internal array can be done by allocating a new, longer array,
 copying the elements, and deallocating the original array. This may raise
 Storage_Error, or cause an exception from a controlled subprogram. We require
-that a failed Reserve_Capacity does not lose any elements if an exception occurs,
-but we do not require a specific order of evaluations or copying.
+that a failed Reserve_Capacity does not lose any elements if an exception
+occurs, but we do not require a specific order of evaluations or copying.
 
 This routine is used to preallocate the internal array to the specified
 capacity such that future Inserts do not require memory allocation overhead.
@@ -719,26 +759,23 @@
 
 function Length (Container : Vector) return Count_Type;
 
-The Length function returns the number of active elements in Container.
-
+Returns the number of elements in Container.
 
 function Is_Empty (Container : Vector) return Boolean;
 
 Equivalent to Length (Container) = 0.
 
-
 procedure Clear (Container : in out Vector);
-
-Sets the length of Vector to 0. Its capacity does not change.
 
+Removes all the elements from Container. The capacity of Container does not
+change.
 
 function To_Cursor (Container : Vector;
                     Index     : Extended_Index) return Cursor;
 
-If the value of Index is not in the range First_Index (Container) .. Last_Index
-(Container), then No_Element is returned. Otherwise, a cursor designating the
-element currently at Index in Container is returned.
-
+If Index is not in the range First_Index (Container) .. Last_Index (Container),
+then No_Element is returned. Otherwise, a cursor designating the
+element at position Index in Container is returned.
 
 function To_Index (Position  : Cursor) return Extended_Index;
 
@@ -759,42 +796,50 @@
    return Element_Type;
 
 If Index is not in the range First_Index (Container) .. Last_Index (Container),
-then Constraint_Error is propagated. Otherwise this function returns the
-element at position Index.
+then Constraint_Error is propagated. Otherwise, Element returns the element at
+position Index.
 
-
 function Element (Position  : Cursor) return Element_Type;
 
-Returns the element designated by Position. If Position equals No_Element,
-then Constraint_Error is propagated.
+If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
+Element returns the element designated by Position.
 
 procedure Query_Element
-   (Container : in Vector;
-    Index     : in Index_Type;
-    Process   : not null access procedure (Element : in Element_Type));
+  (Container : in Vector;
+   Index     : in Index_Type;
+   Process   : not null access procedure (Element : in Element_Type));
 
 If Index is not in the range First_Index (Container) .. Last_Index (Container),
-then Constraint_Error is propagated. Otherwise, it calls Process.all with the
-element at position Index as the parameter. Any exception raised by Process
-is propagated.
+then Constraint_Error is propagated. Otherwise, Query_Element calls Process.all
+with the element at position Index as the argument. Program_Error is propagated
+if Process.all tampers with the elements of Container. Any exception raised
+by Process.all is propagated.
 
 procedure Query_Element
-   (Position : in Cursor;
-    Process  : not null access procedure (Element : in Element_Type));
+  (Position : in Cursor;
+   Process  : not null access procedure (Element : in Element_Type));
 
-Calls Process.all with the element designated by Position as the parameter. If
-Position equals No_Element, then Constraint_Error is propagated. Any exceptions
-raised by Process are propagated.
+If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
+Query_Element calls Process.all with the element designated by Position as the
+argument. Program_Error is propagated if Process.all tampers with the elements
+of Container. Any exception raised by Process.all is propagated.
 
+AARM Note: The tamper with the elements check is intended to prevent the
+Element parameter of Process from being modified or deleted outside of
+Process. The check prevent data loss (if Element_Type is passed by copy)
+or erroneous execution (if Element_Type is an unconstrained type in
+an indefinite container).
+
 procedure Update_Element
-    (Container : in Vector;
-     Index     : in Index_Type;
-     Process   : not null access procedure (Element : in out Element_Type));
+  (Container : in Vector;
+   Index     : in Index_Type;
+   Process   : not null access procedure (Element : in out Element_Type));
 
 If Index is not in the range First_Index (Container) .. Last_Index (Container),
-then Constraint_Error is propagated. Otherwise, it calls Process.all with the
-element at position Index as the parameter. Any exception raised by Process
-is propagated.
+then Constraint_Error is propagated. Otherwise, Update_Element calls Process.all
+with the element at position Index as the argument. Program_Error is propagated
+if Process.all tampers with the elements of Container. Any exception raised by
+Process.all is propagated.
 
 If Element_Type is unconstrained and definite, then the Element parameter
 of Process.all shall be unconstrained.
@@ -811,12 +856,13 @@
 to do that reliably.
 
 procedure Update_Element
-   (Position : in Cursor;
-    Process : not null access procedure (Element : in out Element_Type));
+  (Position : in Cursor;
+   Process  : not null access procedure (Element : in out Element_Type));
 
-Calls Process.all with the element designated by Position as the parameter. If
-Position equals No_Element, then Constraint_Error is propagated. Any exceptions
-raised by Process are propagated.
+If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
+Update_Element calls Process.all with the element designated by Position as the
+argument. Program_Error is propagated if Process.all tampers with the elements
+of Container. Any exception raised by Process.all is propagated.
 
 If Element_Type is unconstrained and definite, then the Element parameter
 of Process.all shall be unconstrained.
@@ -828,91 +874,83 @@
                            Index     : in Index_Type;
                            By        : in Element_Type);
 
-If Index does not specify a value in the range First_Index (Container) ..
-Last_Index (Container), then Constraint_Error is propagated. Otherwise this
-procedure assigns the value By to the element at position Index. Any exceptions
-raised during the assignment are propagated. The element at position Index is
-not an empty element after successful completion of this operation.
+If Index is not in the range First_Index (Container) .. Last_Index (Container),
+then Constraint_Error is propagated. Otherwise Replace_Element assigns the
+value By to the element at position Index. Any exception raised during the
+assignment is propagated. The element at position Index is not an empty element
+after successful call to Replace_Element.
 
 procedure Replace_Element (Position : in Cursor;
                            By       : in Element_Type);
 
-This procedure assigns the value By to the element designated by Position.
-If Position equals No_Element, then Constraint_Error is propagated.
-Any exception raised during the assignment is propagated. The element
-designated by Position is not an empty element after successful completion of
-this operation.
+If Position equals No_Element, then Constraint_Error is propagated. Otherwise
+Replace_Element assigns By to the element designated by Position. Any exception
+raised during the assignment is propagated. The element at Position is
+not an empty element after successful call to Replace_Element.
 
 AARM Note: Replace_Element and Update_Element are the only ways that an element
 can change from empty to non-empty.
 
-
 procedure Assign (Target : in out Vector;
                   Source : in     Vector);
-
-If Target denotes the same object as Source, then the operation has no
-effect. Otherwise, Assign first calls Clear (Target), then
-Reserve_Capacity (Target, Length (Source)). It then assigns the active elements
-of Source to the corresponding positions in Target, and then sets the length
-of Target to the length of Source. Any exception raised during element
-assignment is propagated.
 
+If Target denotes the same object as Source, then the operation has no effect.
+Otherwise, Assign first calls Clear (Target), then Reserve_Capacity (Target,
+Length (Source)). It then assigns the elements of Source to the corresponding
+positions in Target, and sets the length of Target to the length of Source.
+Any exception raised during element assignment is propagated.
 
 procedure Move (Target : in out Vector;
                 Source : in out Vector);
 
-If Target denotes the same object as Source, then the operation has no
-effect. If Length (Target) is greater than 0, then it raises Constraint_Error.
-Otherwise, the internal array is removed from Source (making its capacity 0)
-and moved to Target (making its capacity the original capacity of Source). The
-length of Target is set to the length of Source, and the length of Source is
-set to 0.
+If Target denotes the same object as Source, then Move has no effect.
+Otherwise, Move first calls Clear (Target); then, each element from Source
+is removed from Source and inserted into Target in the original order. The
+length of Source is 0 after a successful call to Move.
 
 AARM Note:
 
+The idea is that the internal array is removed from Source and moved to Target.
+(See the Implementation Advice for Move).
 If Capacity (Target) /= 0, the previous internal array may need to be
 deallocated. We don't mention this explicitly, because it is covered by the
-"no memory loss" Implementation Requirement. If the deallocation raises an
-exception, the implementation should leave both Vectors in a consistent state
-(usually empty for Target and the original state for Source).
+"no memory loss" Implementation Requirement.
 
-
 procedure Insert (Container : in out Vector;
                   Before    : in     Extended_Index;
                   New_Item  : in     Vector);
 
-If Length(New_Item) is 0, then Insert does nothing. Otherwise, it calculates
-the new length *NL* as the sum of the current length and Length (New_Item); if
-the value of Last appropriate for length NL would be greater than
-Index_Type'Last then Constraint_Error is propagated. If the value of Before is
-not in the range First_Index (Container) .. Last_Index (Container) + 1, then
-Constraint_Error is propagated.
+If Before is not in the range First_Index (Container) ..
+Last_Index (Container) + 1, then Constraint_Error is propagated. If
+Length(New_Item) is 0, then Insert does nothing. Otherwise, it computes the new
+length *NL* as the sum of the current length and Length (New_Item); if the
+value of Last appropriate for length NL would be greater than Index_Type'Last
+then Constraint_Error is propagated.
 
-If the current vector capacity is less than or equal to the new length,
-Reserve_Capacity (Container, NL) is called to increase the vector capacity. Then
-Insert slides the elements in the range Before .. Last_Index (Container) up by
-Length(New_Item) positions, and then copies the elements of New_Item to the
-positions starting at Before. Any exception raised during the copying is
+If the current vector capacity is less than or equal to NL,
+Reserve_Capacity (Container, NL) is called to increase the vector capacity.
+Then Insert slides the elements in the range Before .. Last_Index (Container)
+up by Length(New_Item) positions, and then copies the elements of New_Item to
+the positions starting at Before. Any exception raised during the copying is
 propagated.
 
 AARM Note:
-
 Moving the elements does not necessarily involve copying. Similarly, since
-Reserve_Capacity does not require the copying of elements, it does not need to be
-explicitly called (the implementation can combine the operations if it wishes
-to). [Note to reviewers: I didn't want to duplicate the messy wording and notes
-about exceptions not losing anything.]
+Reserve_Capacity does not require the copying of elements, it does not need to
+be explicitly called (the implementation can combine the operations if it
+wishes to). [Note to reviewers: I didn't want to duplicate the messy wording
+and notes about exceptions not losing anything.]
 End AARM Note.
 
 procedure Insert (Container : in out Vector;
                   Before    : in     Cursor;
                   New_Item  : in     Vector);
 
-If Before is not No_Element, and does not designate an element in Container,
-then Program_Error is propagated.
-If Length(New_Item) is 0, then Insert does nothing.
-If Before is No_Element, then is equivalent to Insert (Container,
-Last_Index (Container) + 1), New_Item); otherwise is
+Program_Error is propagated unless Before is equal to No_Element or
+designated an element in Container. Otherwise, if Length(New_Item) is 0, then
+Insert does nothing.
+If Before is No_Element, then the call is equivalent to Insert (Container,
+Last_Index (Container) + 1), New_Item); otherwise the call is
 equivalent to Insert (Container, To_Index (Before), New_Item);
 
 AARM Note: The check on Before checks that the cursor does not belong to some
@@ -927,19 +965,17 @@
                   New_Item  : in     Vector;
                   Position  :    out Cursor);
 
-If Before is not No_Element, and does not designate an element in Container,
-then Program_Error is propagated.
-If Length(New_Item) is 0, then Insert sets Position to Before. Otherwise,
-create a temporary (call it Temp_Index) and set it to Last_Index (Container) + 1
-if Before equals No_Element, and To_Index (Before) otherwise. Then
-Insert (Container, Before, New_Item) is called, and finally
-Position is set to To_Cursor (Container, Temp_Index).
-
-AARM Note: The messy wording because Before is invalidated by Insert, and we
-don't want Position to be invalid after this call. An implementation probably
-only needs to copy Before to Position.
+Program_Error is propagated unless Before is equal to No_Element or
+designated an element in Container.
+If Before equals No_Element, then
+let T be Last_Index (Container) + 1; otherwise, let T be To_Index (Before).
+Insert (Container, T, New_Item) is called, and then Position is set to
+To_Cursor (Container, T).
+
+AARM Note: The messy wording is needed because Before is invalidated by Insert,
+and we don't want Position to be invalid after this call. An implementation
+probably only needs to copy Before to Position.
 
-
 procedure Insert (Container : in out Vector;
                   Before    : in     Extended_Index;
                   New_Item  : in     Element_Type;
@@ -947,7 +983,6 @@
 
 Equivalent to Insert (Container, Before, To_Vector (New_Item, Count));
 
-
 procedure Insert (Container : in out Vector;
                   Before    : in     Cursor;
                   New_Item  : in     Element_Type;
@@ -955,7 +990,6 @@
 
 Equivalent to Insert (Container, Before, To_Vector (New_Item, Count));
 
-
 procedure Insert (Container : in out Vector;
                   Before    : in     Cursor;
                   New_Item  : in     Element_Type;
@@ -964,88 +998,91 @@
 
 Equivalent to Insert (Container, Before, To_Vector (New_Item, Count), Position);
 
-
 procedure Prepend (Container : in out Vector;
                    New_Item  : in     Vector;
                    Count     : in     Count_Type := 1);
 
 Equivalent to Insert (Container, Index_Type'First, New_Item).
 
-
 procedure Prepend (Container : in out Vector;
                    New_Item  : in     Element_Type;
                    Count     : in     Count_Type := 1);
 
 Equivalent to Insert (Container, Index_Type'First, New_Item, Count).
 
-
 procedure Append (Container : in out Vector;
                   New_Item  : in     Vector);
 
 Equivalent to Insert (Container, Last_Index (Container) + 1, New_Item).
 
-
 procedure Append (Container : in out Vector;
                   New_Item  : in     Element_Type;
                   Count     : in     Count_Type := 1);
 
 Equivalent to Insert (Container, Last_Index (Container) + 1, New_Item, Count).
 
-
 procedure Insert_Space (Container : in out Vector;
                         Before    : in     Extended_Index;
                         Count     : in     Count_Type := 1);
 
-Equivalent to Insert (Container, Before, New_Item, Count), with the
-difference that the inserted elements are empty elements.
+If Before is not in the range First_Index (Container) .. Last_Index (Container)
++ 1, then Constraint_Error is propagated. If Count is 0, then Insert_Space does
+nothing. Otherwise, it computes the new length *NL* as the sum of the current
+length and Count; if the value of Last appropriate for length NL would be
+greater than Index_Type'Last then Constraint_Error is propagated.
+
+If the current vector capacity is less than or equal to NL,
+Reserve_Capacity (Container, NL) is called to increase the vector capacity.
+Then Insert_Space slides the elements in the range Before .. Last_Index
+(Container) up by Count positions, and then inserts empty elements in the
+positions starting at Before.
 
-
 procedure Insert_Space (Container : in out Vector;
                         Before    : in     Cursor;
                         Position  :    out Cursor;
                         Count     : in     Count_Type := 1);
-
-If Before is not No_Element, and does not designate an element in Container,
-then Program_Error is propagated.
-If Length(New_Item) is 0, then Insert does nothing. Otherwise,
-create a temporary (call it Temp_Index) and set it to
-Last_Index (Container) + 1 if Before equals No_Element, and
-To_Index (Before) otherwise. Then Insert_Space (Container, Temp_Index,
-Count) is called, and finally Position is set to To_Cursor (Container,
-Temp_Index).
 
+Program_Error is propagated unless Before is equal to No_Element or
+designated an element in Container.
+If Before equals No_Element, then let T be Last_Index (Container) + 1;
+otherwise, let T be To_Index (Before). Insert_Space (Container, T, Count) is
+called, and then Position is set to To_Cursor (Container, T).
 
 procedure Set_Length (Container : in out Vector;
                       Length    : in     Count_Type);
 
-If Length is larger than the capacity of Container, calls
+If Length is larger than the capacity of Container, Set_Length calls
 Reserve_Capacity (Container, Length), then sets the length of the
 Container to Length. If Length is greater than the original length of
-Container, the added elements are empty elements.
+Container, empty elements are added to Container; otherwise elements are
+are removed from Container.
 
+AARM Ramification: No elements are moved by this operation; any new empty
+elements are added at the end. This follows from the rules that a cursor
+continues to designate the same element unless the the routine is defined
+to make the cursor ambiguous or invalid; this operation does not do that.
 
 procedure Delete (Container : in out Vector;
                   Index     : in     Extended_Index;
                   Count     : in     Count_Type := 1);
 
-If Count is 0, the operation has no effect. If Index does not specify a
-value in the range First_Index (Container) .. Last_Index (Container), then
-Constraint_Error is propagated. Otherwise Delete slides the active
-elements (if any) starting Index plus Count down to Index. Any
-exceptions raised during element assignment are propagated.
+If Index is not in the range First_Index (Container) .. Last_Index (Container),
+then Constraint_Error is propagated. If Count is 0, Delete has no effect.
+Otherwise Delete slides the elements (if any) starting at position Index +
+Count down to Index. Any exception raised during element assignment is
+propagated.
 
 AARM Note: If Index + Count >= Last_Index(Container), this effectively
 truncates the vector (setting Last_Index to Index - 1 and consequently
-setting Length to Index - Index_Type'First).
+sets Length to Index - Index_Type'First).
 
 procedure Delete (Container : in out Vector;
                   Position  : in out Cursor;
                   Count     : in     Count_Type := 1);
 
-If Position is No_Element, this operation has no effect.
-If Position does not designate an element in Container, then Program_Error is
-raised. If Count is 0, the operation has no effect. Otherwise is equivalent to
-Delete (Container, To_Index (Position), Count).
+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, Delete (Container, To_Index (Position), Count) is called.
 
 procedure Delete_First (Container : in out Vector;
                         Count     : in     Count_Type := 1);
@@ -1053,13 +1090,12 @@
 Equivalent to Delete (Container, Index_Type'First, Count).
 
 procedure Delete_Last (Container : in out Vector;
-                       Count      : in     Count_Type := 1);
+                       Count     : in     Count_Type := 1);
 
-If Length (Container) <= Count then is equivalent to
-Clear (Container); otherwise is equivalent to Delete (Container,
+If Length (Container) <= Count then Delete_Last is equivalent to
+Clear (Container). Otherwise it is equivalent to Delete (Container,
 Index_Type'Val(Index_Type'Pos(Last_Index(Container)) - Count + 1), Count).
 
-
 function First_Index (Container : Vector) return Index_Type;
 
 Returns the value Index_Type'First.
@@ -1069,37 +1105,33 @@
 
 function First (Container : Vector) return Cursor;
 
-If Container is empty, First returns the value No_Element. Otherwise,
-returns a cursor that designates the first element in Container.
+If Container is empty, First returns No_Element. Otherwise, it returns a cursor
+that designates the first element in Container.
 
 function First_Element (Container : Vector) return Element_Type;
 
 Equivalent to Element (Container, First_Index (Container)).
 
-
 function Last_Index (Container : Vector) return Extended_Index;
-
-If Container is empty, returns No_Index;
-otherwise, returns the position of the last element in Container.
 
+If Container is empty, Last_Index returns No_Index. Otherwise, it returns the
+position of the last element in Container.
 
 function Last (Container : Vector) return Cursor;
 
-If Container is empty, Last returns the value No_Element. Otherwise,
-returns a cursor that designates the last element in Container.
+If Container is empty, Last returns No_Element. Otherwise, it returns a cursor
+that designates the last element in Container.
 
-
 function Last_Element (Container : Vector) return Element_Type;
 
 Equivalent to Element (Container, Last_Index (Container)).
 
-
 procedure Swap (Container : in Vector;
                 I, J      : in Index_Type);
 
-If I or J does not specify a value in the range First_Index (Container) ..
-Last_Index (Container), then Constraint_Error is propagated. Otherwise
-Swap exchanges the values of the elements at positions I and J.
+If I or J is not in the range First_Index (Container) .. Last_Index (Container),
+then Constraint_Error is propagated. Otherwise, Swap exchanges the values of
+the elements at positions I and J.
 
 AARM Notes: To Be Honest: The implementation is not required to actually
 copy the elements if it can do the swap some other way. But it is allowed
@@ -1149,11 +1181,11 @@
                      Index     : Index_Type := Index_Type'First)
    return Extended_Index;
 
-Searches the elements of Container for an element equal to Item,
-starting at position Index. If there are no elements in the
-range Index .. Last_Index (Container) equal to Item, then Find_Index returns
-No_Index. Otherwise, it returns the index of the matching
-element.
+Searches the elements of Container for an element equal to Item (in the sense
+of the generic formal equality operator). The search starts at position Index
+and proceeds towards Last_Index (Container). If no equal element is found, then
+Find_Index returns No_Index. Otherwise, it returns the index of the first equal
+element encountered.
 
 function Find (Container : Vector;
                Item      : Element_Type;
@@ -1161,25 +1193,25 @@
    return Cursor;
 
 If Position is not No_Element, and does not designate an element in Container,
-then Program_Error is propagated.
-Searches the elements of Container for an element equal to Item,
-starting at the first element if Cursor equals No_Element, and at
-the element designated by Cursor otherwise, and searching to the last
-element in Container. If an item equal to Item is found, Find returns a
-cursor designating the first element found equal to Item. If no such item is
-found, it returns No_Element.
+then Program_Error is propagated. Otherwise Find searches the elements of
+Container for an element equal to Item (in the sense of the generic formal
+equality operator). The search starts at the first element if Cursor equals
+No_Element, and at the element designated by Cursor otherwise. It proceeds
+towards the last element of Container. If no equal element is found, then
+Find returns No_Cursor. Otherwise, it returns a cursor designating the first
+equal element encountered.
 
 function Reverse_Find_Index (Container : Vector;
                              Item      : Element_Type;
                              Index     : Index_Type := Index_Type'Last)
    return Extended_Index;
 
-Searches the elements of Container in reverse for an element equal to
-Item, starting at position Index. If Index is greater than Last_Index
-(Container), then the search begins at position Last_Index (Container).
-If there are no elements in the range Index_Type'First .. Index equal
-to Item, then Reverse_Find_Index returns No_Index.
-Otherwise, it returns the index of the matching element.
+Searches the elements of Container for an element equal to Item (in the sense
+of the generic formal equality operator). The search starts at position Index
+or, if Index is greater than Last_Index (Container), at position Last_Index
+(Container). It proceeds towards First_Index (Container). If no equal element
+is found, then Reverse_Find_Index returns No_Index. Otherwise, it returns the
+index of the first equal element encountered.
 
 function Reverse_Find (Container : Vector;
                        Item      : Element_Type;
@@ -1187,38 +1219,40 @@
    return Cursor;
 
 If Position is not No_Element, and does not designate an element in Container,
-then Program_Error is propagated.
-Searches the elements of Container for an element equal to Item,
-starting at the last element if Cursor equals No_Element, and at
-the element designated by Cursor otherwise, and searching backwards to the
-first element in Container. If an item equal to Item is found, Find returns a
-cursor designating the first element found equal to Item. If no such item is
-found, it returns No_Element.
+then Program_Error is propagated. Otherwise Reverse_Find searches the elements
+of Container for an element equal to Item (in the sense of the generic formal
+equality operator). The search starts at the last element if Cursor equals
+No_Element, and at the element designated by Cursor otherwise. It proceeds
+towards the first element of Container. If no equal element is found, then
+Reverse_Find returns No_Cursor. Otherwise, it returns a cursor designating
+the first equal element encountered.
 
-
 function Contains (Container : Vector;
                    Item      : Element_Type) return Boolean;
 
 Equivalent to Has_Element (Find (Container, Item)).
 
-
 function Next (Position : Cursor) return Cursor;
 
 If Position equals No_Element or designates the last element of the container,
 then Next returns the value No_Element. Otherwise, returns a cursor that
-designates the element with index To_Index (Position) + 1 in the
-same vector as Position.
+designates the element with index To_Index (Position) + 1 in the same vector as
+Position.
 
 function Previous (Position : Cursor) return Cursor;
 
 If Position equals No_Element or designates the first element of the container,
 then Previous returns the value No_Element. Otherwise, returns a cursor that
-designates the element with index (To_Index (Position) - 1) in the
-same vector as Position.
+designates the element with index (To_Index (Position) - 1) in the same vector
+as Position.
+
+procedure Next (Position : in out Cursor);
 
-The procedure Next is equivalent to Position := Next (Position).
+Equivalent to Position := Next (Position).
+
+procedure Previous (Position : in out Cursor);
 
-The procedure Previous is equivalent to Position := Previous (Position).
+Equivalent to Position := Previous (Position).
 
 function Has_Element (Position : Cursor) return Boolean;
 
@@ -1229,19 +1263,23 @@
 use of them (including in this routine) is erroneous.
 
 procedure Iterate
-   (Container : in Vector;
-    Process : not null access procedure (Position : in Cursor));
+  (Container : in Vector;
+   Process   : not null access procedure (Position : in Cursor));
 
 Invokes Process.all with a cursor that designates each element in Container, in
-index order. Any exception raised by Process is propagated.
-Program_Error is propagated if:
- * Process.all attempts to insert or delete elements from Container; or
- * Process.all finalizes Container; or
- * Process.all calls Move with Container as a parameter.
+index order. Program_Error is propagated if Process.all tampers with the
+cursors of Container.
+Any exception raised by Process is propagated.
 
 AARM Note:
-This check takes place when the operations that insert or delete elements, etc.
-are called. There is no check needed if an attempt is made to insert or delete
+The purpose of the tamper with cursors check is to prevent erroneous execution
+from the Position parameter of Process.all becoming invalid. This check takes
+place when the operations that tamper with the cursors of the container are
+called. The check cannot be made later (say in the body of Iterate), because
+that could cause the Position cursor to be invalid and potentially cause
+execution to become erroneous -- defeating the purpose of the check.
+
+There is no check needed if an attempt is made to insert or delete
 nothing (that is, Count = 0 or Length(Item) = 0).
 
 The check is easy to implement: each container needs a counter. The counter
@@ -1254,11 +1292,11 @@
 End AARM Notes.
 
 procedure Reverse_Iterate
-   (Container : in Vector;
-    Process : not null access procedure (Position : in Cursor));
+  (Container : in Vector;
+   Process   : not null access procedure (Position : in Cursor));
 
-Iterates over the nodes in Container as per Iterate, except
-that elements are traversed in reverse order.
+Iterates over the nodes in Container as per Iterate, except that elements are
+traversed in reverse index order.
 
 
 Legality Rules
@@ -1297,7 +1335,8 @@
 
 A Cursor value is *ambiguous* if any of the following have occurred since it
 was created:
-  * Insert or Delete has been called on the vector that contains the element the
+  * Insert, Insert_Space, or Delete has been called on the vector that contains
+    the element the
     cursor designates with an index value (or a cursor designating an element at
     such an index value) less than or equal to the index value of the element
     designated by the cursor;
@@ -1341,11 +1380,6 @@
 invalid cursor parameter. Execution is erroneous if any other subprogram
 declared in Containers.Vectors is called with an invalid cursor parameter.
 
-Execution also is erroneous if the called Process procedure of a call to
-Query_Element or Update_Element executes an operation that causes the Position
-cursor or To_Cursor of the Index parameter of Query_Element or Update_Element
-to become invalid or ambiguous.
-
 AARM Notes: The list above (combined with the bounded error cases) is intended
 to be exhaustive. In other cases, a cursor value continues to designate its
 original element. For instance, cursor values survive the appending of new
@@ -1391,6 +1425,12 @@
 algorithm chosen is one that does not copy items unnecessarily. Bubble sort
 would not meet this advice, for instance.
 
+Move should not copy elements, and should minimize copying of internal
+data structures.
+
+AARM Note: Usually that can be accomplishing simply by moving the pointer(s) to
+the internal data structures from the Source vector to the Target vector.
+
 NOTE:
 All elements of a vector occupy locations in the internal array.
 If a sparse container is required, a Hashed_Map should be used rather than a
@@ -1408,26 +1448,28 @@
 
 A.18.3 The Package Containers.Doubly_Linked_Lists
 
-The language-defined package Containers.Doubly_Linked_Lists provides
+The language-defined generic package Containers.Doubly_Linked_Lists provides
 private types List and Cursor, and a set of operations for each type. A
 list container is optimized for insertion and deletion at any position.
 
 A doubly-linked list container object manages a linked list of internal
-storage nodes, each of which contains an element and pointers to the
+*nodes*, each of which contains an element and pointers to the
 next (successor) and previous (predecessor) internal nodes. A cursor
-designates particular storage nodes (and thus elements) within a list.
+designates a particular node within a list (and by extension the element
+contained in that node). A cursor keeps designating the same node (and element)
+as long as the node is part of the container, even if the node is moved in the
+container.
 
+The *length* of a list is the number of elements it contains.
+
 Static Semantics
 
-The library package Containers.Doubly_Linked_Lists has the following
+The generic library package Containers.Doubly_Linked_Lists has the following
 declaration:
 
 generic
-
    type Element_Type is private;
-
    with function "=" (Left, Right : Element_Type) return Boolean is <>;
-
 package Ada.Containers.Doubly_Linked_Lists is
    pragma Preelaborate (Doubly_Linked_Lists);
 
@@ -1451,12 +1493,12 @@
       return Element_Type;
 
    procedure Query_Element
-       (Position : in Cursor;
-        Process  : not null access procedure (Element : in Element_Type));
+     (Position : in Cursor;
+      Process  : not null access procedure (Element : in Element_Type));
 
    procedure Update_Element
-       (Position : in Cursor;
-        Process : not null access procedure (Element : in out Element_Type));
+     (Position : in Cursor;
+      Process  : not null access procedure (Element : in out Element_Type));
 
    procedure Replace_Element (Position : in Cursor;
                               By       : in Element_Type);
@@ -1563,12 +1605,12 @@
    function Has_Element (Position : Cursor) return Boolean;
 
    procedure Iterate
-       (Container : in List;
-        Process : not null access procedure (Position : in Cursor));
+     (Container : in List;
+      Process   : not null access procedure (Position : in Cursor));
 
    procedure Reverse_Iterate
-       (Container : in List;
-        Process : not null access procedure (Position : in Cursor));
+     (Container : in List;
+      Process   : not null access procedure (Position : in Cursor));
 
 private
 
@@ -1577,53 +1619,92 @@
 end Ada.Containers.Doubly_Linked_Lists;
 
 
-The type List needs finalization (see 7.6).
+The type List is used to represent lists. The type List needs finalization (see
+7.6).
 
-Empty_List represents the empty list. If an object of type List is not
-otherwise initialized, it will be initialized to the same value as
-Empty_List.
+Empty_List represents the empty List object. It has a length of 0. If an object
+of type List is not otherwise initialized, it is initialized to the same value
+as Empty_List.
 
 No_Element represents a cursor that designates no element. If an object of type
-Cursor is not otherwise initialized, it will be initialized to the same
-value as No_Element.
+Cursor is not otherwise initialized, it is initialized to the same value as
+No_Element.
 
+Some operations are assumed to work on a constant set of elements. For such
+an operation, a subprogram is said to *tamper with cursors* of a list object L
+if:
+
+ * it inserts or deletes elements of L, that is, it calls the Insert,
+   Clear, Delete, or Delete_Last procedures with L as a parameter; or
+
+   AARM To Be Honest: Operations which are defined to be equivalent to
+   a call on one of these operations also are included. Similarly, operations
+   which call one of these as part of their definition are included.
+
+ * it reorders the elements of L, that is, it calls the Splice,
+   Swap_Links, or Reverse_List procedures or an instance of Generic_Sort or
+   Generic_Merge with C as a parameter; or
+
+ * it finalizes L; or
+ * it calls the Move procedure with L as a parameter.
+
+Some operations are assumed to not change elements. For such an operation, a
+subprogram is said to *tamper with elements* of a list object L if:
+
+   * it tampers with cursors of L; or
+   * it modifies one or more elements of L, that is, it calls the
+     Replace_Element, Update_Element, or Swap procedures with L as a parameter.
+
+   AARM Note:
+   Swap copies elements rather than reordering them, so it can be allowed
+   for Iterate.
+
 function "=" (Left, Right : List) return Boolean;
+
+If Left and Right denote the same list object, then the function returns True.
+If Left and Right have different lengths, then the function returns False.
+Otherwise, it compares each element in Left to the corresponding element in
+Right using the generic formal equality operator; if element equality returns
+False, then the function returns False. If the function has not returned a
+result after checking all of the elements, it returns True. Any exception
+raised during evaluation of element equality is propagated.
+
+function Length (Container : List) return Count_Type;
+
+Returns the number of elements in Container.
 
-If Left denotes the same object as Right, then this function returns
-True. Otherwise if Left and Right have different lengths, then this
-function returns False. Otherwise, it compares each element in Left to
-the corresponding element in Right using the generic formal equality
-operator. If element equality returns False, then this function returns
-False; otherwise, this function returns True. Any exception raised
-during evaluation of element equality is propagated.
+function Is_Empty (Container : List) return Boolean;
 
-The function Length returns the number of elements in Container.
+Equivalent to Length (Container) = 0.
 
-The function Is_Empty is equivalent to Length (Container) = 0.
+procedure Clear (Container : in out List);
 
-Clear removes all the nodes in Container, and sets the length to 0. Any
-exceptions raised during deallocation of storage are propagated.
+Removes all the elements from Container.
 
 function Element (Position : Cursor) return Element_Type;
 
-Returns the element stored on the node designated by Position. If
-Position equals No_Element, then Constraint_Error is propagated.
+If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
+Element returns the element designated by Position.
 
 procedure Query_Element
-   (Position : in Cursor;
-    Process  : not null access procedure (Element : in Element_Type));
+  (Position : in Cursor;
+   Process  : not null access procedure (Element : in Element_Type));
 
 If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
-Query_Element invokes Process.all with the element on node designated by
-Position as the argument.
+Query_Element calls Process.all with the element on node designated by
+Position as the argument. Program_Error is propagated if Process.all tampers
+with the elements of Container. Any exception raised by Process.all is
+propagated.
 
 procedure Update_Element
-   (Position : in Cursor;
-    Process : not null access procedure (Element : in out Element_Type));
+  (Position : in Cursor;
+   Process  : not null access procedure (Element : in out Element_Type));
 
 If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
-Update_Element invokes Process.all with the element on node designated by
-Position as the argument.
+Update_Element calls Process.all with the element on node designated by
+Position as the argument. Program_Error is propagated if Process.all tampers
+with the elements of Container. Any exceptions raised by Process.all are
+propagated.
 
 If Element_Type is unconstrained and definite, then the Element parameter
 of Process.all shall be unconstrained.
@@ -1635,34 +1716,42 @@
 procedure Replace_Element (Position : Cursor;
                            By       : Element_Type);
 
-Assigns the value By to the element stored on the node designated by
-Position. If Position equals No_Element, then Constraint_Error is
-propagated.
+If Position equals No_Element, then Constraint_Error is propagated. Otherwise
+Replace_Element assigns the value By to the element designated by
+Position.
 
 procedure Move (Target : in out List;
                 Source : in out List);
+
+If Target denotes the same object as Source, then Move has no
+effect. Otherwise, Move first calls Clear (Target). Then, the nodes in Source
+are moved to Target (in the original order). The length of Target is set to the
+length of Source, and the length of Source is set to 0.
 
-If Target denotes the same object as Source, then the operation has no
-effect. If Length (Target) is greater than 0, then it raises
-Constraint_Error. Otherwise, the nodes in Source are moved to Target. The
-length of Target is set to the length of Source, and the length of Source is
-set to 0.
+procedure Prepend (Container : in out List;
+                   New_Item  : in     Element_Type;
+                   Count     : in     Count_Type := 1);
 
-Prepend is equivalent to Insert (Container, First (Container), New_Item, Count).
+Equivalent to Insert (Container, First (Container), New_Item, Count).
+
+procedure Append (Container : in out List;
+                  New_Item  : in     Element_Type;
+                  Count     : in     Count_Type := 1);
 
-Append is equivalent to Insert (Container, No_Element, New_Item, Count).
+Equivalent to Insert (Container, No_Element, New_Item, Count).
 
 procedure Insert (Container : in out List;
                   Before    : in     Cursor;
                   New_Item  : in     Element_Type;
                   Count     : in     Count_Type := 1);
 
-If Before is not No_Element, and does not designate an element in Container,
-then Program_Error is propagated.
-Insert allocates Count new nodes whose element is initialized to the value
-New_Item, and inserts them prior to the node designated by Before. If
-Before equals No_Element, the new nodes are inserted immediately
-following the last node (if any).
+Program_Error is propagated unless Before is equal to No_Element or
+designated an element in Container.
+Otherwise, Insert inserts Count copies of
+New_Item prior to the element designated by Before. If Before equals
+No_Element, the new elements are inserted after the last node (if any). Any
+exception raised during allocation of internal storage is propagated, and
+Container is not modified.
 
 AARM Note: The check on Before checks that the cursor does not belong to some
 other Container. This check implies that a reference to the container is
@@ -1677,54 +1766,50 @@
                   Position  :    out Cursor;
                   Count     : in     Count_Type := 1);
 
-If Before is not No_Element, and does not designate an element in Container,
-then Program_Error is propagated.
-Insert allocates Count new nodes whose element is initialized to the value
-New_Item, and inserts them prior to the node designated by Before. If
-Before equals No_Element, the new nodes are inserted immediately
-following the last node (if any). Position designates the first
-newly-inserted node. Any exception raised during allocation of
-internal storage is propagated, and Container is not modified.
+Program_Error is propagated unless Before is equal to No_Element or
+designated an element in Container.
+Otherwise, Insert allocates Count copies of
+New_Item, and inserts them prior to the element designated by Before. If Before
+equals No_Element, the new elements are inserted after the last element (if
+any). Position designates the first newly-inserted element. Any exception
+raised during allocation of internal storage is propagated, and Container is
+not modified.
 
 procedure Insert (Container : in out List;
                   Before    : in     Cursor;
                   Position  :    out Cursor;
                   Count     : in     Count_Type := 1);
 
-If Before is not No_Element, and does not designate an element in Container,
-then Program_Error is propagated.
-Allocates Count new nodes with elements initialized with any implicit initial
-values for any part (as for an object_declaration with no initialization
-expression - see 3.3.1), and inserts them prior to the node designated by
-Before. If Before equals No_Element, the new node is inserted immediately
-following the last node (if any). Position designates the first newly-inserted
-node. Any exception raised during allocation of internal storage is
-propagated, and Container is not modified.
+Program_Error is propagated unless Before is equal to No_Element or
+designated an element in Container.
+Otherwise, Insert inserts Count new elements
+prior to the element designated by Before. If Before equals No_Element, the new
+elements are inserted after the last node (if any). The new elements are
+initialized with any implicit initial value for any part (as for an
+object_declaration with no initialization expression - see 3.3.1). Any
+exception raised during allocation of internal storage is propagated, and
+Container is not modified.
 
 procedure Delete (Container : in out List;
                   Position  : in out Cursor;
                   Count     : in     Count_Type := 1);
 
-If Position equals No_Element, this operation has no effect. If Position does
-not designate an element in Container, then Program_Error is propagated. Otherwise
-Delete removes Count nodes starting at the node designated by Position from
-Container (or all of the nodes if there are less than Count nodes starting at
-Position). Any exception raised during deallocation of internal storage is
-propagated.
+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 Delete removes (from Container) Count elements starting at the
+element designated by Position (or all of the elements if there are less than
+Count elements starting at Position).
 
 procedure Delete_First (Container : in out List;
                         Count     : in     Count_Type := 1);
 
-If Length(Container) >= Count, Delete_First removes the first Count nodes from
-Container; otherwise, all of the nodes in Container are removed. Any exceptions
-raised during deallocation of storage are propagated.
+Equivalent to Delete (Container, First (Container), Count).
 
 procedure Delete_Last (Container : in out List;
                        Count     : in     Count_Type := 1);
 
-If Length(Container) >= Count, Delete_Last removes the last Count nodes from
-Container; otherwise, all of the nodes in Container are removed. Any exceptions
-raised during deallocation of storage are propagated.
+If Length (Container) <= Count then Delete_Last is equivalent to Clear
+(Container). Otherwise it removes the last Count nodes from Container.
 
 generic
    with function "<" (Left, Right : Element_Type) return Boolean is <>;
@@ -1750,19 +1835,24 @@
 procedure Generic_Merge (Target  : in out List;
                          Source  : in out List);
 
-If Source denotes the same object as Target, the operation has no
-effect. Otherwise this operation reorders nodes such that they are
-removed from Source and moved to Target. Target and Source are assumed to be
-sorted smallest first as determined by the generic formal "<" operator. The
-nodes in Source containing elements that are less than elements in Target are
-spliced in before the elements already in Target. The nodes in Source container
-elements that are equal to or greater than elements in Target are spliced in
-after the elements already in Target. Any exception raised during evaluation
-of "<" is propagated, immediately terminating the merge operation.
+Generic_Merge removes elements from Source and inserts them into Target so that
+Target be sorted smallest first as determined by the generic formal "<"
+operator.
+
+Any exception raised during evaluation of "<" is propagated. If Target and
+Source are not sorted smallest first, then Program_Error is propagated. In
+these cases, Target is left in an unspecified order, but contains the union of
+the elements that were initially in Source and Target; Source is left empty.
 
+AARM Note:
+If Program_Error is propagated by Generic_Merge because one of the lists was
+unsorted, it is possible to recover by sorting Target. If Source and Target
+designate the same object, Generic_Merge is essentially a no-op, but it still
+has to check that the list is sorted.
+
 procedure Reverse_List (Container : in out List);
 
-Reorders the nodes of Container in reverse order.
+Reorders the elements of Container in reverse order.
 
 procedure Swap (I, J  : in Cursor);
 
@@ -1795,62 +1885,58 @@
                   Before   : in     Cursor;
                   Source   : in out List);
 
-If Before is not No_Element, and does not designate an element in Target,
-then Program_Error is propagated.
-If Source denotes the same object as Target, the operation has no
-effect. Otherwise, Splice reorders nodes such that they are removed from
-Source and moved to Target, just prior to Before. If Before equals
-No_Element, the nodes of Source are spliced after the last node of
-Target. The length of Target is incremented by the number of
-nodes in Source, and the length of Source is set to 0.
+Program_Error is propagated unless Before is equal to No_Element or
+designated an element in Target. Otherwise, if Source denotes the
+same object as Target, the
+operation has no effect. Otherwise, Splice reorders elements such that they are
+removed from Source and moved to Target, immediately prior to Before. If Before
+equals No_Element, the nodes of Source are spliced after the last node of
+Target. The length of Target is incremented by the number of nodes in Source,
+and the length of Source is set to 0.
 
 procedure Splice (Target   : in out List;
                   Before   : in     Cursor;
                   Position : in     Cursor);
 
 If either of Before or Position is not No_Element, and does not designate an
-element in Target, then Program_Error is propagated.
-If Position equals No_Element, or if Position equals Before, or if the
-successor of Position equals Before, the operation has no effect.
-Otherwise the node designated by Position becomes the predecessor of Before.
-If Before equals No_Element, then Position is moved after the last node.
+element in Target, then Program_Error is propagated. If Position equals
+No_Element, or if Position equals Before, or if the successor of Position
+equals Before, the operation has no effect. Otherwise the element designated by
+Position is moved immediately prior to Before, or, if Before equals No_Element,
+after the last element.
 
 procedure Splice (Target   : in out List;
                   Before   : in     Cursor;
                   Source   : in out List;
                   Position : in     Cursor);
 
-If Before does not equal No_Element, and does not designate a node in
-Target, then Program_Error is propagated. If Position does not equal
-No_Element, and does not designate a node in Source, then Program_Error
-is propagated.
-If Source denotes the same object as Target, then Splice is
-equivalent to the Splice operation sans Source parameter. If Position
-equals No_Element, the operation has no effect. Otherwise the node
-designated by Position is removed from Source and moved to Target, immediately
-prior to Before. If Before equals No_Element, then Position is moved after the
-last node of Target. The length of Target is incremented, and the length of
-Source is decremented.
+If Position is No_Element then Constraint_Error is propagated. If Before does
+not equal No_Element, and does not designate an element in Target, then
+Program_Error is propagated. If Position does not equal No_Element, and does
+not designate a node in Source, then Program_Error is propagated. If Source
+denotes the same object as Target, then Splice is equivalent to Splice (Target,
+Before, Position). Otherwise the element designated by Position is removed from
+Source and moved to Target, immediately prior to Before, or, if Before equals
+No_Element, after the last element of Target. The length of Target is
+incremented, and the length of Source is decremented.
 
 function First (Container : List) return Cursor;
 
-Returns a cursor that designates the first node. If Container is empty,
-First returns the value No_Element.
+If Container is empty, First returns the value No_Element. Otherwise it returns
+a cursor that designates the first node in Container.
 
 function First_Element (Container : List) return Element_Type;
 
-If Container is empty, then Constraint_Error is propagated. Otherwise,
-it returns Element (First (Container)).
+Equivalent to Element (First (Container)).
 
 function Last (Container : List) return Cursor;
 
-Returns a cursor that designates the last node. If Container is empty,
-Last returns the value No_Element.
+If Container is empty, Last returns the value No_Element. Otherwise it returns a
+cursor that designates the last node in Container.
 
 function Last_Element (Container : List) return Element_Type;
 
-If Container is empty, then Constraint_Error is propagated. Otherwise,
-it returns Element (Last (Container)).
+Equivalent to Element (Last (Container)).
 
 function Contains (Container : List;
                    Item      : Element_Type) return Boolean;
@@ -1863,11 +1949,12 @@
   return Cursor;
 
 If Position is not No_Element, and does not designate an element
-in Container, then Program_Error is propagated.
-Searches the nodes of Container for an element equal to Item. The
-search starts at the node designated by Position. If Position equals
-No_Element, then the search begins at the first node. If no element is
-found that matches Item, then Find returns the value No_Element.
+in Container, then Program_Error is propagated. Find searches the elements of
+Container for an element equal to Item (in the sense of the generic formal
+equality operator). The search starts at the element designated by Position, or
+at the first element if Position equals No_Element. It proceeds towards Last
+(Container). If no equal element is found, then Find returns No_Element.
+Otherwise, it returns a cursor designating the first equal element encountered.
 
 function Reverse_Find (Container : List;
                        Item      : Element_Type;
@@ -1875,28 +1962,33 @@
    return Cursor;
 
 If Position is not No_Element, and does not designate an element
-in Container, then Program_Error is propagated.
-Searches the nodes of Container in reverse for an element equal to Item.
-The search starts at the node designated by Position. If Position
-equals No_Element, then the search begins at the last node. If no
-element is found that matches Item, then Find returns the value
-No_Element.
+in Container, then Program_Error is propagated. Find searches the elements of
+Container for an element equal to Item (in the sense of the generic formal
+equality operator). The search starts at the element designated by Position, or
+at the lastelement if Position equals No_Element. It proceeds towards First
+(Container). If no equal element is found, then Reverse_Find returns
+No_Element. Otherwise, it returns a cursor designating the first equal element
+encountered.
 
 function Next (Position : Cursor) return Cursor;
 
-If Position equals No_Element or designates the last node of the container,
-then Next returns the value No_Element. Otherwise, returns a cursor that
-designates the successor of the node designated by Position.
+If Position equals No_Element or designates the last element of the container,
+then Next returns the value No_Element. Otherwise, it returns a cursor that
+designates the successor of the element designated by Position.
 
 function Previous (Position : Cursor) return Cursor;
 
-If Position equals No_Element or designates the first node of the container,
-then Previous returns the value No_Element. Otherwise, returns a cursor that
-designates the predecessor of the node designated by Position.
+If Position equals No_Element or designates the first element of the container,
+then Previous returns the value No_Element. Otherwise, it returns a cursor that
+designates the predecessor of the element designated by Position.
+
+procedure Next (Position : in out Cursor);
+
+Equivalent to Position := Next (Position).
 
-The procedure Next is equivalent to Position := Next (Position).
+procedure Previous (Position : in out Cursor);
 
-The procedure Previous is equivalent to Position := Previous (Position).
+Equivalent to Position := Previous (Position).
 
 function Has_Element (Position : Cursor) return Boolean;
 
@@ -1907,34 +1999,32 @@
 use of them (including in this routine) is erroneous.
 
 procedure Iterate
-   (Container : in List;
-    Process : not null access procedure (Position : in Cursor));
+  (Container : in List;
+   Process   : not null access procedure (Position : in Cursor));
 
-Invokes Process.all with a cursor that designates each node in Container. Any
-exceptions raised during Process are propagated.
-Program_Error is propagated if:
- * Process.all attempts to insert or delete elements from Container; or
- * Process.all calls a routine that reorders the elements of Container
-   (Swap_Links, Splice, Generic_Sort, or Generic_Merge); or
- * Process.all finalizes Container; or
- * Process.all calls Move with Container as a parameter.
+Iterate calls Process.all with a cursor that designates each node in Container,
+starting with the first node and moving the cursor as per the Next function.
+Program_Error is propagated if Process.all tampers with the cursors of
+Container. Any exception raised by Process.all is propagated.
 
 AARM Note:
-This check takes place when the operations that insert or delete elements, etc.
-are called. There is no check needed if an attempt is made to insert or delete
-nothing (that is, Count = 0).
+The purpose of the tamper with cursors check is to prevent erroneous execution
+from the Position parameter of Process.all becoming invalid. This check takes
+place when the operations that tamper with the cursors of the container are
+called. The check cannot be made later (say in the body of Iterate), because
+that could cause the Position cursor to be invalid and potentially cause
+execution to become erroneous -- defeating the purpose of the check.
 
 See Iterate for vectors for a suggested implementation of the check.
-
-Swap is not included here, as it only copies elements.
 End AARM Notes.
 
 procedure Reverse_Iterate
-   (Container : in List;
-    Process : not null access procedure (Position : in Cursor));
+  (Container : in List;
+   Process   : not null access procedure (Position : in Cursor));
 
-Iterates over the nodes in Container as per Iterate, except
-that elements are traversed in reverse order.
+Iterates over the nodes in Container as per Iterate, except that elements are
+traversed in reverse order, starting with the last node and moving the cursor
+as per the Previous function.
 
 Erroneous Execution
 
@@ -1949,10 +2039,6 @@
 cursor parameter. Execution is erroneous if any other subprogram declared in
 Containers.Doubly_Linked_Lists is called with an invalid cursor parameter.
 
-Execution also is erroneous if the called Process procedure of a call to
-Query_Element or Update_Element executes an operation that causes the Position
-cursor of Query_Element or Update_Element to become invalid.
-
 AARM Notes: The list above is intended to be exhaustive. In other cases, a
 cursor value continues to designate its original element. For instance,
 cursor values survive the insertion and deletion of other nodes.
@@ -1960,7 +2046,7 @@
 While it is possible to check for these cases, in many cases the overhead
 necessary to make the check is substantial in time or space. Implementations
 are encouraged to check for as many of these cases as possible and raise
-Constraint_Error if detected.
+Program_Error if detected.
 End AARM Notes.
 
 Implementation Requirements
@@ -1992,6 +2078,12 @@
 In other words, we're requiring the use of a better than O(N**2) sorting
 algorithm, such as Quicksort. No Bubble sorts allowed!
 
+Move should not copy elements, and should minimize copying of internal
+data structures.
+
+AARM Note: Usually that can be accomplishing simply by moving the pointer(s) to
+the internal data structures from the Source container to the Target container.
+
 NOTE
 Sorting a list never copies elements, and is a stable sort (equal elements
 remain in the original order). This is different than sorting an array or
@@ -2000,17 +2092,20 @@
 
 A.18.4 Maps
 
-The language-defined packages Containers.Hashed_Maps and Containers.Ordered_Maps
-provide private types Map and Cursor, and a set of operations for each type.
-A map container allows an arbitrary type to be used as a key to find the
-element associated with that key. A hashed map uses a hash function to organize
-the keys, while an ordered map orders the keys per a specified relation.
+The language-defined generic packages Containers.Hashed_Maps and
+Containers.Ordered_Maps provide private types Map and Cursor, and a set of
+operations for each type. A map container allows an arbitrary type to be used
+as a key to find the element associated with that key. A hashed map uses a hash
+function to organize the keys, while an ordered map orders the keys per a
+specified relation.
 
 This section describes the declarations that are common to both kinds of maps.
 See A.18.5 for a description of the semantics specific to Containers.Hashed_Maps
 and A.18.6 for a description of the semantics specific to
 Containers.Ordered_Maps.
 
+Static Semantics
+
 The type Map is used to represent maps. The type Map needs finalization (see
 7.6).
 
@@ -2028,6 +2123,33 @@
 in the map exactly once until the last node is reached. The exact definition of
 these terms is different for hashed maps and ordered maps.
 
+Some operations are assumed to work on a constant set of elements. For such
+an operation, a subprogram is said to *tamper with cursors* of a map object M
+if:
+
+ * it inserts or deletes elements of M, that is, it calls the Insert,
+   Include, Clear, Delete, or Exclude procedures with M as a parameter; or
+
+   AARM To Be Honest: Operations which are defined to be equivalent to
+   a call on one of these operations also are included. Similarly, operations
+   which call one of these as part of their definition are included.
+
+ * it finalizes M; or
+ * it calls the Move procedure with M as a parameter; or
+ * it calls one of the operations defined to tamper with the cursors of M.
+
+Some operations are assumed to not change elements. For such an operation, a
+subprogram is said to *tamper with elements* of a map object M if:
+
+   * it tampers with cursors of M; or
+   * it modifies one or more elements of M, that is, it calls the
+     Replace, Replace_Element, or Update_Element procedures with M as a
+     parameter.
+
+   AARM Note:
+   Replace only modifies a key and element rather than rehashing, so it can be
+   allowed for Iterate.
+
 Empty_Map represents the empty Map object. It has a length of 0. If an object
 of type Map is not otherwise initialized, it is initialized to the same
 value as Empty_Map.
@@ -2060,9 +2182,7 @@
 
 procedure Clear (Container : in out Map);
 
-Removes all the nodes from Container. Any exception raised during deallocation
-of
-storage is propagated.
+Removes all the nodes from Container.
 
 function Key (Position : Cursor) return Key_Type;
 
@@ -2075,22 +2195,26 @@
 Element returns the element component of the node designated by Position.
 
 procedure Query_Element
-   (Position : in Cursor;
-    Process  : not null access procedure (Key     : in Key_Type;
-                                          Element : in Element_Type));
+  (Position : in Cursor;
+   Process  : not null access procedure (Key     : in Key_Type;
+                                         Element : in Element_Type));
 
 If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
 Query_Element calls Process.all with the key and element from the node
-designated by Position as the arguments.
+designated by Position as the arguments. Program_Error is propagated if
+Process.all tampers with the elements of Container. Any exceptions raised by
+Process.all are propagated.
 
 procedure Update_Element
-   (Position : in Cursor;
-    Process : not null access procedure (Key     : in Key_Type;
+  (Position : in Cursor;
+   Process  : not null access procedure (Key     : in Key_Type;
                                          Element : in out Element_Type));
 
 If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
 Update_Element calls Process.all with the key and element from the node
-designated by Position as the arguments.
+designated by Position as the arguments. Program_Error is propagated if
+Process.all tampers with the elements of Container. Any exceptions raised
+by Process.all are propagated.
 
 If Element_Type is unconstrained and definite, then the Element parameter
 of Process.all shall be unconstrained.
@@ -2103,15 +2227,16 @@
                            By       : in Element_Type);
 
 If Position equals No_Element, then Constraint_Error is propagated.
-Otherwise this operation assigns By to the element of the node designated by
+Otherwise Replace_Element assigns By to the element of the node designated by
 Position.
 
 procedure Move (Target : in out Map;
                 Source : in out Map);
 
-Move first clears Target. Then each node from Source is removed from Source and
-inserted into Target. The length of Source is 0 after a successful call to
-Move.
+If Target denotes the same object as Source, then Move has no effect.
+Otherwise, Move first calls Clear (Target). Then, each node from Source is
+removed from Source and inserted into Target. The length of Source is 0 after a
+successful call to Move.
 
 procedure Insert (Container : in out Map;
                   Key       : in     Key_Type;
@@ -2199,10 +2324,10 @@
 procedure Delete (Container : in out Map;
                   Position  : in out Cursor);
 
-If Position equals No_Element, Delete has no effect. If Position does not
-designate an element in Container, then Program_Error is propagated. Otherwise,
-Delete removes the node designated by Position from the map. Position is set to
-No_Element on return.
+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, Delete removes the node designated by Position from the map.
+Position is set to No_Element on return.
 
 AARM Note: The check on Position checks that the cursor does not belong to some
 other map. This check implies that a reference to the map is included in the
@@ -2258,16 +2383,13 @@
 deleted elements; such cursors are invalid (see below).
 
 procedure Iterate
-   (Container : in Map;
-    Process : not null access procedure (Position : in Cursor));
+  (Container : in Map;
+   Process   : not null access procedure (Position : in Cursor));
 
 Iterate calls Process.all with a cursor that designates each node in Container,
 starting with the first node and moving the cursor according to the successor
-relation. Any exception raised by Process.all is propagated. Program_Error is
-propagated if:
- * Process.all attempts to insert or delete nodes from Container; or
- * Process.all finalizes Container; or
- * Process.all calls Move with Container as a parameter.
+relation. Program_Error is propagated if Process.all tampers with the elements
+of Container. Any exception raised by Process.all is propagated.
 
 AARM Note:
 This check takes place when the operations that insert or delete elements, etc.
@@ -2285,15 +2407,11 @@
     Source or Target of a call to Move;
   * The node it designates has been deleted from the map.
 
-The result of "=" or Has_Element is unspecified if these function are called
+The result of "=" or Has_Element is unspecified if these functions are called
 with an invalid cursor parameter. Execution is erroneous if any other subprogram
 declared in Containers.Hashed_Maps or Containers.Ordered_Maps is called with an
 invalid cursor parameter.
 
-Execution also is erroneous if the called Process.all procedure of a call to
-Query_Element or Update_Element executes an operation that causes the Position
-cursor of Query_Element or Update_Element to become invalid.
-
 AARM Notes: The list above is intended to be exhaustive. In other cases, a
 cursor value continues to designate its original element. For instance, cursor
 values survive the insertion and deletion of other nodes.
@@ -2309,27 +2427,29 @@
 No storage associated with a Map object shall be lost upon assignment or
 scope exit.
 
+Implementation Advice
+
+Move should not copy elements, and should minimize copying of internal
+data structures.
+
+AARM Note: Usually that can be accomplishing simply by moving the pointer(s) to
+the internal data structures from the Source container to the Target container.
+
 A.18.5 The Package Containers.Hashed_Maps
 
 Static Semantics
 
-The library package Containers.Hashed_Maps has the following
+The generic library package Containers.Hashed_Maps has the following
 declaration:
 
 generic
-
    type Key_Type is private;
-
    type Element_Type is private;
-
    with function Hash (Key : Key_Type) return Hash_Type;
-
    with function Equivalent_Keys (Left, Right : Key_Type)
       return Boolean;
-
    with function "=" (Left, Right : Element_Type)
       return Boolean is <>;
-
 package Ada.Containers.Hashed_Maps is
    pragma Preelaborate (Hashed_Maps);
 
@@ -2354,14 +2474,14 @@
    function Element (Position : Cursor) return Element_Type;
 
    procedure Query_Element
-       (Position : in Cursor;
-        Process  : not null access procedure (Key     : in Key_Type;
-                                              Element : in Element_Type));
+     (Position : in Cursor;
+      Process  : not null access procedure (Key     : in Key_Type;
+                                            Element : in Element_Type));
 
    procedure Update_Element
-      (Position : in Cursor;
-       Process : not null access procedure (Key     : in Key_Type;
-                                            Element : in out Element_Type));
+    (Position : in Cursor;
+     Process  : not null access procedure (Key     : in Key_Type;
+                                           Element : in out Element_Type));
 
    procedure Replace_Element (Position : in Cursor;
                               By       : in Element_Type);
@@ -2433,8 +2553,8 @@
       return Boolean;
 
    procedure Iterate
-       (Container : in Map;
-        Process : not null access procedure (Position : in Cursor));
+     (Container : in Map;
+      Process   : not null access procedure (Position : in Cursor));
 
    function Capacity (Container : Map) return Count_Type;
 
@@ -2618,20 +2738,6 @@
 
 Equivalent to Equivalent_Keys (Left, Key (Right)).
 
-procedure Iterate
-   (Container : in Map;
-    Process : not null access procedure (Position : in Cursor));
-
-In addition to the semantics described in A.18.4, Program_Error is propagated
-if Process.all calls Reserve_Capacity.
-
-AARM Note:
-See Iterate for vectors for a suggested implementation of the check.
-
-We have to include Reserve_Capacity here, as rehashing probably will change
-the order that elements are stored in the map.
-End AARM Notes.
-
 function Capacity (Container : Map) return Count_Type;
 
 Returns the capacity of Container.
@@ -2642,11 +2748,13 @@
 Reserve_Capacity allocates a new hash table such that the length of the
 resulting map can become at least the value Capacity without requiring an
 additional call to Reserve_Capacity, and is large enough to hold the current
-length of Map. Reserve_Capacity then rehashes the nodes in Container onto the
-new hash table. It replaces the old hash table with the new hash table, and
+length of Container. Reserve_Capacity then rehashes the nodes in Container onto
+the new hash table. It replaces the old hash table with the new hash table, and
 then deallocates the old hash table. Any exception raised during allocation is
 propagated and Container is not modified.
 
+Reserve_Capacity tampers with the cursors of Container.
+
 AARM Notes: This routine is used to preallocate the internal hash table to the
 specified capacity such that future Inserts do not require expansion of the
 hash table. Therefore, the implementation should allocate the needed memory to
@@ -2657,6 +2765,9 @@
 specify whether an implementation actually supports reduction of the capacity.
 Since the actual capacity can be anything greater than or equal to Count, an
 implementation never has to reduce the capacity.
+
+Reserve_Capacity tampers with the cursors, as rehashing probably will change
+the order that elements are stored in the map.
 End AARM Notes
 
 Implementation Advice
@@ -2681,18 +2792,14 @@
 
 Static Semantics
 
-The package Containers.Ordered_Maps has the following declaration:
+The generic library package Containers.Ordered_Maps has the following
+declaration:
 
 generic
-
    type Key_Type is private;
-
    type Element_Type is private;
-
    with function "<" (Left, Right : Key_Type) return Boolean is <>;
-
    with function "=" (Left, Right : Element_Type) return Boolean is <>;
-
 package Ada.Containers.Ordered_Maps is
    pragma Preelaborate (Ordered_Maps);
 
@@ -2832,7 +2939,7 @@
 end Ada.Containers.Ordered_Maps;
 
 Two keys K1 and K2 are *equivalent* if both K1 < K2 and K2 < K1 return False,
-using the generic formal less-than operator for keys.
+using the generic formal "<" operator for keys.
 
 Functions "<" and "=" on Key_Type values are expected to return the same result
 value each time they are called with a particular pair of key values. If A = B
@@ -2880,17 +2987,19 @@
 successor of a node is the node with the smallest key that is larger than the
 key of the given node. The predecessor of a node is the node with the largest
 key that is smaller than the key of the given node. All comparisons are done
-using the generic formal less-than operator for keys.
+using the generic formal "<" operator for keys.
 
 procedure Delete_First (Container : in out Map);
 
 If Container is empty, Delete_First has no effect. Otherwise the node
-designated by First (Container) is removed from Container.
+designated by First (Container) is removed from Container. Delete_First
+tampers with the cursors of Container.
 
 procedure Delete_Last (Container : in out Map);
 
 If Container is empty, Delete_Last has no effect. Otherwise the node designated
-by Last (Container) is removed from Container.
+by Last (Container) is removed from Container. Delete_Last tampers with
+the cursors of Container.
 
 function Floor (Container : Map;
                 Key       : Key_Type) return Cursor;
@@ -2903,7 +3012,7 @@
                   Key       : Key_Type) return Cursor;
 
 Ceiling searches for the first node whose key is not less than Key, using the
-generic formal less-than operator for keys. If such a node is found, a cursor
+generic formal "<" operator for keys. If such a node is found, a cursor
 that designates it is returned. Otherwise No_Element is returned.
 
 function First_Key (Container : Map) return Key_Type;
@@ -2963,8 +3072,8 @@
 Equivalent to Key (Right) < Left.
 
 procedure Reverse_Iterate
-   (Container : in Map;
-    Process : not null access procedure (Position : in Cursor));
+  (Container : in Map;
+   Process   : not null access procedure (Position : in Cursor));
 
 Iterates over the nodes in Container as per Iterate, with the difference that
 the nodes are traversed in predecessor order, starting with the last node.
@@ -2990,7 +3099,7 @@
 
 A.18.7 Sets
 
-The language-defined packages Containers.Hashed_Sets and
+The language-defined generic packages Containers.Hashed_Sets and
 Containers.Ordered_Sets provide private types Set and Cursor, and a set of
 operations for each type. A set container allows elements of an arbitrary type
 to be stored without duplication. A hashed set uses a hash function to organize
@@ -3001,6 +3110,8 @@
 Containers.Hashed_Sets and A.18.9 for a description of the semantics specific
 to Containers.Ordered_Sets.
 
+Static Semantics
+
 The type Set is used to represent sets. The type Set needs finalization (see
 7.6).
 
@@ -3017,6 +3128,33 @@
 last element is reached. The exact definition of these terms is different for
 hashed sets and ordered sets.
 
+Some operations are assumed to work on a constant set of elements. For such
+an operation, a subprogram is said to *tamper with cursors* of a set object S
+if:
+
+ * it inserts or deletes elements of S, that is, it calls the Insert,
+   Include, Clear, Delete, Exclude, or Replace_Element procedures with S as
+   a parameter; or
+
+   AARM To Be Honest: Operations which are defined to be equivalent to
+   a call on one of these operations also are included. Similarly, operations
+   which call one of these as part of their definition are included.
+
+   AARM Disucssion: We have to include Replace_Element here because it might
+   delete and reinsert the element if it moves in the set.
+
+ * it finalizes S; or
+ * it calls the Move procedure with S as a parameter; or
+ * it calls one of the operations defined to tamper with cursors of S.
+
+Some operations are assumed to not change elements. For such an operation, a
+subprogram is said to *tamper with elements* of a set object S if:
+
+   * it tampers with cursors of S; or
+   * it modifies one or more elements of S, that is, it calls the
+     Replace or Update_Element_Preserving_Key procedures with S as a
+     parameter.
+
 Empty_Set represents the empty Set object. It has a length of 0. If an object
 of type Set is not otherwise initialized, it is initialized to the same
 value as Empty_Set.
@@ -3030,8 +3168,18 @@
 If Left and Right denote the same set object, then the function returns True.
 If Left and Right have different lengths, then the function returns False.
 Otherwise, for each element E in Left, the function returns False if an element
+equal to E (in the sense of the generic formal equality operator) is not
+present in Right. If the function has not returned a result after checking all
+of the elements, it returns True. Any exception raised during evaluation of
+element equality is propagated.
+
+function Equivalent_Sets (Left, Right : Set) return Boolean;
+
+If Left and Right denote the same set object, then the function returns True.
+If Left and Right have different lengths, then the function returns False.
+Otherwise, for each element E in Left, the function returns False if an element
 equivalent to E is not present in Right. If the function has not returned a
-result after checking all of the elements, it return True. Any exception raised
+result after checking all of the elements, it returns True. Any exception raised
 during evaluation of element equivalence is propagated.
 
 function Length (Container : Set) return Count_Type;
@@ -3044,8 +3192,7 @@
 
 procedure Clear (Container : in out Set);
 
-Removes all the elements from Container. Any exception raised during
-deallocation of storage is propagated.
+Removes all the elements from Container.
 
 function Element (Position : Cursor) return Element_Type;
 
@@ -3053,12 +3200,14 @@
 Element returns the element designated by Position.
 
 procedure Query_Element
-   (Position : in Cursor;
-    Process  : not null access procedure (Element : in Element_Type));
+  (Position : in Cursor;
+   Process  : not null access procedure (Element : in Element_Type));
 
 If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
 Query_Element calls Process.all with the element designated by Position as the
-argument.
+argument. Program_Error is propagated if Process.all tampers with the
+elements of Container.
+Any exceptions raised by Process.all are propagated.
 
 procedure Replace_Element (Container : in Set;
                            Position  : in Cursor;
@@ -3066,18 +3215,19 @@
 
 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 equivalent Replace 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.
+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.
 
 procedure Move (Target : in out Set;
                 Source : in out Set);
 
-Move first clears Target. Then each element from Source is removed from Source
-and inserted into Target. The length of Source is 0 after a successful call to
-Move.
+If Target denotes the same object as Source, then Move has no effect.
+Otherwise, Move first clears Target. Then, each element from Source is removed
+from Source and inserted into Target. The length of Source is 0 after a
+successful call to Move.
 
 procedure Insert (Container : in out Set;
                   New_Item  : in     Element_Type;
@@ -3185,16 +3335,13 @@
 deleted elements; such cursors are invalid (see below).
 
 procedure Iterate
-   (Container : in Set;
-    Process : not null access procedure (Position : in Cursor));
+  (Container : in Set;
+   Process   : not null access procedure (Position : in Cursor));
 
 Iterate calls Process.all with a cursor that designates each element in
 Container, starting with the first node and moving the cursor according to the
-successor relation. Any exception raised by Process.all is propagated.
-Program_Error is propagated if:
- * Process.all attempts to insert or delete elements from Container; or
- * Process.all finalizes Container; or
- * Process.all calls Move with Container as a parameter.
+successor relation. Program_Error is propagated if Process.all tampers with
+the elements of Container. Any exception raised by Process.all is propagated.
 
 AARM Note:
 This check takes place when the operations that insert or delete elements, etc.
@@ -3291,39 +3438,37 @@
 
 The subprograms in package Generic_Keys named Contains, Find, Element, Delete,
 and Exclude, are equivalent to the corresponding subprograms in the parent
-package, with the difference that the Key parameter is used locate an element in
-the set.
+package, with the difference that the Key parameter is used locate an element
+in the set.
 
 procedure Replace (Container : in out Set;
                    Key       : in     Key_Type;
                    New_Item  : in     Element_Type);
 
-Equivalent to Replace (Container, Find (Container, Key), New_Item).
+Equivalent to Replace_Element (Container, Find (Container, Key), New_Item).
 
 function Key (Position : Cursor) return Key_Type;
 
 Equivalent to Key (Element (Position)).
 
-procedure Checked_Update_Element
-    (Container : in out Set;
-     Position  : in     Cursor;
-     Process   : not null access procedure (Element : in out Element_Type));
+procedure Update_Element_Preserving_Key
+  (Container : in out Set;
+   Position  : in     Cursor;
+   Process   : not null access procedure (Element : in out 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, Checked_Update_Element uses Key to save the key value K of the
-element designated by Position. Checked_Update_Element then calls Process.all
-with that element as the argument. After Process.all returns,
-Checked_Update_Element checks if K determines the same equivalence class as
-that for the new element; if not, the element is removed from the set, then
-inserted back into the set. If the insertion fails, Program_Error is
-propagated.
+Otherwise, Update_Element_Preserving_Key uses Key to save the key value K of the
+element designated by Position. Update_Element_Preserving_Key then calls
+Process.all with that element as the argument. Program_Error is propagated
+if Process.all tampers with the elements of Container. Any exception raised by
+Process.all is propagated. After Process.all returns,
+Update_Element_Preserving_Key checks if K determines the same equivalence class
+as that for the new element; if not, the element is removed from the set and
+Program_Error is propagated.
 
 AARM Note: The key check insures that the invariants of the set are preserved
-by the modification. If not, we try to re-insert the element at the correct
-place. If that fails, we have no choice other than to drop the element
-completely, because saving a value to roll back to would be expensive and
-defeat the purpose of this routine (which is cheap, in-place modifications).
+by the modification.
 
 If Element_Type is unconstrained and definite, then the Element parameter
 of Process.all shall be unconstrained.
@@ -3346,10 +3491,6 @@
 subprogram declared in Containers.Hashed_Sets or Containers.Ordered_Sets is
 called with an invalid cursor parameter.
 
-Execution also is erroneous if the called Process.all procedure of a call to
-Query_Element or Checked_Update_Element executes an operation that causes the
-Position cursor of Query_Element or Checked_Update_Element to become invalid.
-
 AARM Notes: The list above is intended to be exhaustive. In other cases, a
 cursor value continues to designate its original element. For instance, cursor
 values survive the insertion and deletion of other elements.
@@ -3365,21 +3506,27 @@
 No storage associated with a Set object shall be lost upon assignment or scope
 exit.
 
+Implementation Advice
+
+Move should not copy elements, and should minimize copying of internal
+data structures.
+
+AARM Note: Usually that can be accomplishing simply by moving the pointer(s) to
+the internal data structures from the Source container to the Target container.
+
 A.18.8 The Package Containers.Hashed_Sets
 
 Static Semantics
 
-The package Containers.Hashed_Sets has the following declaration:
+The generic library package Containers.Hashed_Sets has the following
+declaration:
 
 generic
-
    type Element_Type is private;
-
    with function Hash (Element : Element_Type) return Hash_Type;
-
    with function Equivalent_Elements (Left, Right : Element_Type)
                  return Boolean;
-
+   with function "=" (Left, Right : Element_Type) return Boolean is <>;
 package Ada.Containers.Hashed_Sets is
    pragma Preelaborate (Hashed_Sets);
 
@@ -3393,6 +3540,8 @@
 
    function "=" (Left, Right : Set) return Boolean;
 
+   function Equivalent_Sets (Left, Right : Set) return Boolean;
+
    function Length (Container : Set) return Count_Type;
 
    function Is_Empty (Container : Set) return Boolean;
@@ -3504,16 +3653,11 @@
                                Capacity  : in     Count_Type);
 
    generic
-
       type Key_Type (<>) is limited private;
-
       with function Key (Element : in Element_Type) return Key_Type;
-
       with function Hash (Key : Key_Type) return Hash_Type;
-
       with function Equivalent_Keys (Left : Key_Type; Right : Element_Type)
                                      return Boolean;
-
    package Generic_Keys is
 
       function Contains (Container : Set;
@@ -3540,7 +3684,7 @@
       procedure Exclude (Container : in out Set;
                          Key       : in     Key_Type);
 
-      procedure Checked_Update_Element
+      procedure Update_Element_Preserving_Key
         (Container : in out Set;
          Position  : in     Cursor;
          Process   : not null access procedure (Element : in out Element_Type));
@@ -3577,10 +3721,11 @@
 
 Function Equivalent_Elements is expected to return the same value each time
 it is called with a particular pair of element values. For any two elements E1
-and E2, the boolean values Equivalent_Keys (E1, E2) and Equivalent_Key (E2, E1)
-are expected to be equal. If Equivalent_Elements behaves in some other manner,
-the behavior of this package is unspecified. Which subprograms of this package
-call Equivalent_Elements, and how many times they call it, is unspecified.
+and E2, the boolean values Equivalent_Elements (E1, E2) and
+Equivalent_Elements (E2, E1) are expected to be equal. If Equivalent_Elements
+behaves in some other manner, the behavior of this package is unspecified.
+Which subprograms of this package call Equivalent_Elements, and how many times
+they call it, is unspecified.
 
 If the value of an element stored in a set is changed other than by an
 operation in this package such that at least one of Hash or Equivalent_Elements
@@ -3629,13 +3774,6 @@
 
 Equivalent to Equivalent_Elements (Left, Element (Right)).
 
-procedure Iterate
-   (Container : in Set;
-    Process : not null access procedure (Position : in Cursor));
-
-In addition to the semantics described in A.18.7, Program_Error is propagated
-if Process.all calls Reserve_Capacity.
-
 function Capacity (Container : Set) return Count_Type;
 
 Returns the capacity of Container.
@@ -3646,12 +3784,17 @@
 Reserve_Capacity allocates a new hash table such that the length of the
 resulting set can become at least the value Capacity without requiring an
 additional call to Reserve_Capacity, and is large enough to hold the current
-length of Set. Reserve_Capacity then rehashes the nodes in Container onto the
-new hash table. It replaces the old hash table with the new hash table, and
+length of Container. Reserve_Capacity then rehashes the nodes in Container onto
+the new hash table. It replaces the old hash table with the new hash table, and
 then deallocates the old hash table. Any exception raised during allocation is
 propagated and Container is not modified.
 
+Reserve_Capacity tampers with the cursors of Container.
 
+AARM Note:
+Reserve_Capacity tampers with the cursors, as rehashing probably will change
+the relationships of the elements in Container.
+
 For any element E, the function Generic_Keys.Hash must be such that Hash (E) =
 Generic_Keys.Hash (Key (E)). If Key or Generic_Keys.Hash behave in some other
 manner, the behavior of Generic_Keys is unspecified. Which subprograms of
@@ -3659,7 +3802,7 @@
 unspecified.
 
 For any two elements E1 and E2, the boolean values Equivalent_Element (E1, E2),
-Equivalent_Keys (Key (E1), E2) and Equivalent_Keys (Key (E2), E1) are all
+Equivalent_Keys (Key (E1), E2), and Equivalent_Keys (Key (E2), E1) are all
 expected to be equal. If Key or Equivalent behave in some other manner, the
 behavior of Generic_Keys is unspecified. Which subprograms of Generic_Keys call
 Equivalent, and how many times they call it, is unspecified.
@@ -3692,16 +3835,13 @@
 
 Static Semantics
 
-The package Containers.Ordered_Sets has the following declaration:
+The generic library package Containers.Ordered_Sets has the following
+declaration:
 
 generic
-
    type Element_Type is private;
-
    with function "<" (Left, Right : Element_Type) return Boolean is <>;
-
    with function "=" (Left, Right : Element_Type) return Boolean is <>;
-
 package Ada.Containers.Ordered_Sets is
    pragma Preelaborate (Ordered_Sets);
 
@@ -3715,6 +3855,8 @@
 
    function "=" (Left, Right : Set) return Boolean;
 
+   function Equivalent_Sets (Left, Right : Set) return Boolean;
+
    function Length (Container : Set) return Count_Type;
 
    function Is_Empty (Container : Set) return Boolean;
@@ -3724,8 +3866,8 @@
    function Element (Position : Cursor) return Element_Type;
 
    procedure Query_Element
-       (Position : in Cursor;
-        Process  : not null access procedure (Element : in Element_Type));
+     (Position : in Cursor;
+      Process  : not null access procedure (Element : in Element_Type));
 
    procedure Replace_Element (Container : in Set;
                               Position  : in Cursor;
@@ -3845,25 +3987,20 @@
       return Boolean;
 
    procedure Iterate
-       (Container : in Set;
-        Process : not null access procedure (Position : in Cursor));
+     (Container : in Set;
+      Process   : not null access procedure (Position : in Cursor));
 
    procedure Reverse_Iterate
-       (Container : in Set;
-        Process : not null access procedure (Position : in Cursor));
+     (Container : in Set;
+      Process   : not null access procedure (Position : in Cursor));
 
    generic
-
       type Key_Type (<>) is limited private;
-
       with function Key (Element : Element_Type) return Key_Type;
-
       with function "<" (Left : Key_Type; Right : Element_Type)
-          return Boolean is <>;
-
+         return Boolean is <>;
       with function ">" (Left : Key_Type; Right : Element_Type)
-          return Boolean is <>;
-
+         return Boolean is <>;
    package Generic_Keys is
 
        function Contains (Container : Set;
@@ -3909,7 +4046,7 @@
        function ">" (Left : Key_Type; Right : Cursor)
           return Boolean;
 
-       procedure Checked_Update_Element
+       procedure Update_Element_Preserving_Key
           (Container : in out Set;
            Position  : in     Cursor;
            Process   : not null access procedure
@@ -3924,7 +4061,7 @@
 end Ada.Containers.Ordered_Sets;
 
 Two elements E1 and E2 are *equivalent* if both E1 < E2 and E2 < E1 return
-False, using the generic formal less-than operator for elements.
+False, using the generic formal "<" operator for elements.
 
 Functions "<" and "=" on Element_Type values are expected to return the same
 result value each time they are called with a particular pair of element values.
@@ -3949,17 +4086,19 @@
 greater than all the other elements in the set. The successor of an element is
 the smallest element that is larger than the given element. The predecessor of
 an element is the largest element that is smaller than the given element. All
-comparisons are done using the generic formal less-than operator for elements.
+comparisons are done using the generic formal "<" operator for elements.
 
 procedure Delete_First (Container : in out Set);
 
 If Container is empty, Delete_First has no effect. Otherwise the element
-designated by First (Container) is removed from Container.
+designated by First (Container) is removed from Container. Delete_First
+tampers with the cursors of Container.
 
 procedure Delete_Last (Container : in out Set);
 
 If Container is empty, Delete_Last has no effect. Otherwise the element
-designated by Last (Container) is removed from Container.
+designated by Last (Container) is removed from Container. Delete_Last
+tampers with the cursors of Container.
 
 function Floor (Container : Set;
                 Item      : Element_Type) return Cursor;
@@ -4024,8 +4163,8 @@
 Equivalent to Element (Right) < Left.
 
 procedure Reverse_Iterate
-   (Container : in Set;
-    Process : not null access procedure (Position : in Cursor));
+  (Container : in Set;
+   Process   : not null access procedure (Position : in Cursor));
 
 Iterates over the elements in Container as per Iterate, with the difference
 that the elements are traversed in predecessor order, starting with the last
@@ -4059,15 +4198,15 @@
 
 A.18.10 The Package Containers.Indefinite_Vectors
 
-The language-defined package Containers.Indefinite_Vectors provides a
+The language-defined generic package Containers.Indefinite_Vectors provides a
 private type Vector and a set of operations. It provides the same
 operations as the package Vectors does, with the difference that the
 generic formal Element_Type is indefinite.
 
 Static Semantics
 
-The declaration of the library package Containers.Indefinite_Vectors has
-the same contents as Containers.Vectors except:
+The declaration of the generic library package Containers.Indefinite_Vectors
+has the same contents as Containers.Vectors except:
 
    * The generic formal Element_Type is indefinite.
 
@@ -4077,7 +4216,7 @@
 
 A.18.11 The Package Containers.Indefinite_Doubly_Linked_Lists
 
-The language-defined package Containers.Indefinite_Doubly_Linked_Lists
+The language-defined generic package Containers.Indefinite_Doubly_Linked_Lists
 provides private types List and Cursor, and a set of operations for each
 type. It provides the same operations as the package Doubly_Linked_Lists
 does, with the difference that the generic formal Element_Type is
@@ -4085,7 +4224,7 @@
 
 Static Semantics
 
-The declaration of the library package
+The declaration of the generic library package
 Containers.Indefinite_Doubly_Linked_Lists has the same contents as
 Containers.Doubly_Linked_Lists except:
 
@@ -4113,15 +4252,16 @@
 
 A.18.12 The Package Containers.Indefinite_Hashed_Maps
 
-The language-defined package Containers.Indefinite_Hashed_Maps provides
+The language-defined generic package Containers.Indefinite_Hashed_Maps provides
 a map with the same operations as the package Hashed_Maps, with the
 difference that the generic formal types Key_Type and Element_Type are
 indefinite.
 
 Static Semantics
 
-The declaration of the library package Containers.Indefinite_Hashed_Maps
-has the same contents as Containers.Hashed_Maps except:
+The declaration of the generic library package
+Containers.Indefinite_Hashed_Maps has the same contents as
+Containers.Hashed_Maps except:
 
   * The generic formal Key_Type is indefinite.
 
@@ -4149,15 +4289,16 @@
 
 A.18.13 The Package Containers.Indefinite_Ordered_Maps
 
-The language-defined package Containers.Indefinite_Ordered_Maps provides
-a map with the same operations as the package Ordered, with the
+The language-defined generic package Containers.Indefinite_Ordered_Maps
+provides a map with the same operations as the package Ordered, with the
 difference that the generic formal types Key_Type and Element_Type are
 indefinite.
 
 Static Semantics
 
-The declaration of the library package Containers.Indefinite_Ordered_Maps
-has the same contents as Containers.Ordered_Maps except:
+The declaration of the generic library package
+Containers.Indefinite_Ordered_Maps has the same contents as
+Containers.Ordered_Maps except:
 
   * The generic formal Key_Type is indefinite.
 
@@ -4185,49 +4326,51 @@
 
 A.18.14 The Package Containers.Indefinite_Hashed_Sets
 
-The language-defined package Containers.Indefinite_Hashed_Sets provides
+The language-defined generic package Containers.Indefinite_Hashed_Sets provides
 a set with the same operations as the package Hashed_Sets, with the
 difference that the generic formal type Element_Type is indefinite.
 
 Static Semantics
 
-The declaration of the library package Containers.Indefinite_Hashed_Sets
+The declaration of the generic library package Containers.Indefinite_Hashed_Sets
 has the same contents as Containers.Hashed_Sets except:
 
   * The generic formal Element_Type is indefinite.
 
   * The Element parameter of access subprogram Process of
-    Checked_Update_Element may be constrained even if Element_Type is
+    Update_Element_Preserving_Key may be constrained even if Element_Type is
     unconstrained.
 
 
 A.18.15 The Package Containers.Indefinite_Ordered_Sets
 
-The language-defined package Containers.Indefinite_Ordered_Sets provides
+The language-defined generic package Containers.Indefinite_Ordered_Sets provides
 a set with the same operations as the package Ordered_Sets, with the
 difference that the generic formal type Element_Type is indefinite.
 
 Static Semantics
 
-The declaration of the library package Containers.Indefinite_Ordered_Sets
-has the same contents as Containers.Ordered_Sets except:
+The declaration of the generic library package
+Containers.Indefinite_Ordered_Sets has the same contents as
+Containers.Ordered_Sets except:
 
   * The generic formal Element_Type is indefinite.
 
   * The Element parameter of access subprogram Process of
-    Checked_Update_Element may be constrained even if Element_Type is
+    Update_Element_Preserving_Key may be constrained even if Element_Type is
     unconstrained.
 
 
 A.18.16 Array Sorting
 
-The language-defined procedures Containers.Generic_Array_Sort and
+The language-defined generic procedures Containers.Generic_Array_Sort and
 Containers.Generic_Constrained_Array_Sort provide sorting on
 arbitrary array types.
 
 Static Semantics
 
-The procedure Containers.Generic_Array_Sort has the following declaration:
+The generic library procedure Containers.Generic_Array_Sort has the following
+declaration:
 
    generic
       type Index_Type is (<>);
@@ -4239,8 +4382,8 @@
    pragma Pure (Ada.Containers.Generic_Array_Sort);
 
 Reorders the elements of Container such that the elements are
-sorted smallest first as determined by the generic formal less-than operator
-provided. Any exception raised during evaluation of less-than is propagated.
+sorted smallest first as determined by the generic formal "<" operator
+provided. Any exception raised during evaluation of "<" is propagated.
 
 AARM Notes
 This implies swapping the elements, usually including an intermediate copy.
@@ -4255,8 +4398,8 @@
 implementation to do that, but it is mostly extra overhead -- usually there
 is something already in the element that provides the needed stability.
 
-The procedure Containers.Generic_Constrained_Array_Sort has the following
-declaration:
+The generic library procedure Containers.Generic_Constrained_Array_Sort has the
+following declaration:
 
    generic
       type Index_Type is (<>);
@@ -4269,15 +4412,15 @@
    pragma Pure (Ada.Containers.Generic_Constrained_Array_Sort);
 
 Reorders the elements of Container such that the elements are
-sorted smallest first as determined by the generic formal less-than operator
-provided. Any exception raised during evaluation of less-than is propagated.
+sorted smallest first as determined by the generic formal "<" operator
+provided. Any exception raised during evaluation of "<" is propagated.
 
 Implementation Advice
 
 The worst-case time complexity of a call on an instantiation of
 Containers.Generic_Array_Sort or Containers.Generic_Constrained_Array_Sort
 should be O(N**2) or better, and the average time complexity should be better
-than O(N**2).
+than O(N**2), where *N* is the length of the Container parameter.
 
 AARM Note
 In other words, we're requiring the use of a sorting algorithm better than
@@ -4310,11 +4453,11 @@
       ...
    end Copy;
 
-The Reserve_Capacity operation tells the vector object to preallocate an internal
-array having at least the capacity specified. If you need to perform many
-repeated insertions, then if you know the ultimate length apriori you
-should always call Reserve_Capacity beforehand. This is more efficient because it
-allocates the internal array once, and therefore avoids the repeated
+The Reserve_Capacity operation tells the vector object to preallocate an
+internal array having at least the capacity specified. If you need to perform
+many repeated insertions, then if you know the ultimate length apriori you
+should always call Reserve_Capacity beforehand. This is more efficient because
+it allocates the internal array once, and therefore avoids the repeated
 reallocation, copying, and deallocation cycles that might be necessary
 otherwise as the array is expanded.
 
@@ -4337,7 +4480,7 @@
 the element changes from empty to non-empty.
 
 The procedure Set_Length can be used to change the length of a vector
-outside of a declarative region.  (One could use To_Vector too, of
+outside of a declarative region. (One could use To_Vector too, of
 course, but it's more efficient to use Set_Length, since that operation
 allocates a new array only if the capacity of the existing array is too
 small.)
@@ -4411,8 +4554,8 @@
 The internal array is managed by the implementation, and there is no
 requirement that it has any particular capacity; the only requirement is that
 the actual capacity is the same or larger than the most recent call to
-Reserve_Capacity. Thus Reserve_Capacity (V, 0) might, but might not, deallocate the
-internal array. If you want to clear the vector and also deallocate the
+Reserve_Capacity. Thus Reserve_Capacity (V, 0) might, but might not, deallocate
+the internal array. If you want to clear the vector and also deallocate the
 internal array, you can use Move:
 
    procedure Clear_And_Deallocate (V : in out Vector) is
@@ -4436,7 +4579,7 @@
 effecting this action prior to calling the operation. As an example,
 suppose we have a vector whose elements are access objects, and we need
 to deallocate the element when it is "popped" from the vector using
-Delete_Last.  We can do that like this:
+Delete_Last. We can do that like this:
 
    procedure Pop (V : in out Vector) is
 
@@ -4480,7 +4623,7 @@
       end loop;
    end Op;
 
-Here we iterate over all of the vector elements.  Alternatively we could
+Here we iterate over all of the vector elements. Alternatively we could
 use a passive iterator:
 
    procedure Op (V : in Vector) is
@@ -4556,7 +4699,7 @@
       Replace_Element (V, Index => I, By => E); -- aka V(I) := E;
    end;
 
-All containers are non-limited, and hence allow ordinary assignment.  In
+All containers are non-limited, and hence allow ordinary assignment. In
 the unique case of a vector, there is a separate assignment procedure:
 
    Assign (Target => V1, Source => V2);
@@ -4845,7 +4988,7 @@
 
 What I need to do is correlate the file descriptor reported in the RT
 signal to a session object. With a map it's almost trivial. In the body
-I can instantiate the map as follows.  First we make a hash function for
+I can instantiate the map as follows. First we make a hash function for
 socket descriptors:
 
    function Hash_FD (fd : in C.int) return Ada.Containers.Hash_Type is
@@ -5048,7 +5191,7 @@
 
    end Print_Results;
 
-Here we use the passive iterator for maps to populate the array.  As
+Here we use the passive iterator for maps to populate the array. As
 with all containers, it's usually simpler and more efficient to use a
 passive iterator if you're going to traverse all the elements in the
 container.
@@ -5425,7 +5568,7 @@
    end Shutdown_Sessions;
 
 The passive iterator visits all the sessions in the map and Free's them;
-this also sets all of the map elements to null.  We then Clear the map,
+this also sets all of the map elements to null. We then Clear the map,
 which sets its length to 0.
 
 
@@ -5664,7 +5807,7 @@
       end loop;
    end Shutdown_Connections;
 
-Here we use the cursor-form of Delete.  This is probably more efficient
+Here we use the cursor-form of Delete. This is probably more efficient
 than using the item-form of Delete, since the cursor-form doesn't have
 to search for the item.
 
@@ -5810,7 +5953,7 @@
       Position : Cursor := Find (Employees, Key => SSN);
    begin
       if Has_Element (Position) then
-         SSN_Keys.Checked_Update_Element
+         SSN_Keys.Update_Element_Preserving_Key
             (Container => Employees,
              Position  => Position,
              Process   => Set_Home'Address);
@@ -5821,12 +5964,11 @@
 Modifying a set element requires special handling, since a set orders
 its elements by key. Indiscriminate changes to element values are
 therefore not allowed, as this would break the set abstraction if the
-order relation were changed. The operation Checked_Update_Element
+order relation were changed. The operation Update_Element_Preserving_Key
 allows the element to be modified, but it checks to determine whether
-the key has changed, and if so it moves the element to a new position
-that preserves the order relation among existing elements. In this
+the key has changed, and if so raises Program_Error. In this
 example we only modify the Home component of the Element_Type record, so
-Checked_Update_Element would not need to take any further action.
+the key portion is not changed and no exception will be raised.
 
 
 Now let's say that the employee's wallet was stolen, which contained his
@@ -5834,9 +5976,9 @@
 apply for a new social security number, and then change his entry in the
 database.
 
-One way to do this would be to first copy the employee object and remove
-it from the set, then change the value of its SSN field, and finally
-(re)insert the element:
+This can be done by first copying the employee object and removing
+it from the set, then changing the value of its SSN field, and finally
+(re)inserting the element:
 
    procedure Change_SSN
      (Old_SSN : SSN_Type;
@@ -5874,59 +6016,11 @@
    end Change_SSN;
 
 
-Another technique is to use Checked_Update_Element, which allows the
-element's key to be modified, and then moves then element to its new
-relative location in the set:
+Suppose now we want a list all the employees in the firm. One way to do
+it is like this:
 
-   procedure Change_SSN
-     (Old_SSN : SSN_Type;
-      New_SSN : SSN_Type) is
+   procedure Display is
 
-      Old_Position, New_Position : Cursor;
-      Inserted                   : Boolean;
-   begin
-      if New_SSN = Old_SSN then
-        return;
-      end if;
-
-      Old_Position := Find (Employees, Key => Old_SSN);
-
-      if not Has_Element (Old_Position) then
-        return;
-      end if;
-
-      New_Position := Find (Employees, Key => New_SSN);
-
-      if Has_Element (New_Position) then
-         raise Duplicate_SSN;
-      end if;
-
-      declare
-         procedure Set_SSN (Employee : in out Employee_Type) is
-         begin
-            Employee.SSN := New_SSN;
-         end;
-      begin
-         SSN_Keys.Checked_Update_Element
-           (Container => Employees,
-            Position  => Old_Position,
-            Process   => Set_SSN'Access);
-      end;
-   end Change_SSN;
-
-Changing the key this way is probably more efficient than deleting and
-then immediately re-inserting the element, since the element doesn't
-need to be copied, and there is no deallocation and re-allocation of the
-element's internal node. When it detects that the element's key has
-been changed, Checked_Update_Element works by first removing the node
-from the tree and then inserting the same node back into the tree.
-
-
-Suppose now we want a list all the employees in the firm. One way to do
-it is like this:
-
-   procedure Display is
-
       procedure Print (I : in Employee_Sets.Cursor) is
 
          procedure Do_Print (E : in Employee_Type) is
@@ -6023,7 +6117,7 @@
 
 Implementing the sort order relation turns out to slightly tricky,
 because we don't want to make a copy of the employee just do get its
-name.  We use nested process routines for Query_Element to create a
+name. We use nested process routines for Query_Element to create a
 context in which both employee objects are directly visible, and then
 compare employee names by querying the employee elements directly.
 
@@ -6119,2544 +6213,4920 @@
 same. The only real difference is where the key lives.
 
 
---!corrigendum A.18
+!comment We assume that AI-344 is included in the Amendment in the wording
+!comment below.
+!corrigendum A.4.9
 
+@dinsc
 
-!ACATS Test
+@i<@s8<Static Semantics>>
 
-ACATS tests will be needed for this library.
+The library function Strings.Hash has the following declaration:
 
-!appendix
+@xcode<@b<with> Ada.Containers;
+@b<function> Ada.Strings.Hash (Key : String) @b<return> Containers.Hash_Type;
+@b<pragma> Pure (Ada.Strings.Hash);>
 
-Report of the ARG Select Committee on Containers
-February 3, 2004
+@xindent<Return an implementation-defined value which is a function of the
+value of Key. If A and B are strings such that A equals B, Hash(A) equals
+Hash(B).>
 
+The library function Strings.Unbounded.Hash has the following declaration:
 
-Executive Summary
+@xcode<@b<with> Ada.Containers;
+@b<function> Ada.Strings.Unbounded.Hash (Key : Unbounded_String) @b<return>
+    Containers.Hash_Type;
+@b<pragma> Preelaborate (Ada.Strings.Unbounded.Hash);>
 
-The committee selected the second proposal as a starting point for a
-standard containers library, with a number of simple changes. The
-changes were simple enough that we produced a version of the library with
-the changes made (AI-00302-3/01).
+@xindent<Return an implementation-defined value which is a function of the
+value of Key. If A and B are unbounded strings such that A equals B, Hash(A)
+equals Hash(B).>
 
-The resulting proposal is not much larger than the Vector and Matrix
-libraries already adopted for the standard. It also should be a good seed
-for a more encompassing secondary standard.
+@i<@s8<Implementation Advice>>
 
-Therefore, we recommend that the ARG adopt this alternative for the standard.
+The various Hash functions should be good hash functions, returning
+a wide spread of values for different string values. It should be unlikely
+for similar strings to return the same value.
 
-     By the ARG Select Committee on Containers:
+!corrigendum A.18
 
-           Randy Brukardt
-           Bob Duff
-           Tucker Taft
+@dinsc
+This clause presents the specifications of the package Containers and
+several child packages, which provide facilities for storing collections
+of elements.
 
-Full Report
+A variety of sequence and associative containers are provided. Each container
+includes a @i<cursor> type. A cursor is a reference to an element within a
+container. Many operations on cursors are common to all of the containers.
 
-Goals
+Within this clause we provide Implementation Advice for the desired
+average or worst case time complexity of certain operations on a
+container. This advice is expressed using a big-O notation.
+A complexity of O(f(N)), presuming f is some function of a
+length parameter N and t(N) is the time the operation takes
+(on average or worst case, as specified) for the length N,
+means that there exists a finite A such that for any N, t(N)/f(N) < A.
 
-A core library of containers is an important addition to Ada. Other competitive
-programming languages include standard sets of containers, and these are
-widely used. Users often note that a standard set of containers is a missing
-piece of Ada. In addition, adding such containers to the standard is not
-a large burden on implementers.
+If the advice suggests that the complexity should be less than
+O(f(N)), then for any arbitrarily small positive real D, there
+should exist a positive integer M such that for all N > M,
+t(N)/f(N) < D.
 
-However, the resources available for work on the standard preclude adding a
-large container library to the standard. If the library is too large, it will
-be insufficiently reviewed, and that has the danger of providing something
-useless.
+!corrigendum A.18.1
 
-Therefore, the committee settled on a limited set of goals:
-   (1) To provide a number of the most useful containers to Ada users in
-       a standard fashion;
-   (2) To provide a framework for future work in this area (hopefully leading
-       to a secondary or de-facto standard).
+@dinsc
+The package Containers is the root of the containers subsystem.
 
-We considered other goals as well. Performance issues were deemed of secondary
-importance. Most uses of containers (indeed, most software) do not have
-critical performance requirements. To provide a library with the variety of
-components needed to meet critical requirements (bounded and unbounded forms,
-array and list implementations, etc.) would be beyond the resources available
-to work on the standard. Moreover, the existence of many components actually
-makes construction of simple applications harder: the programmer has to choose
-a component based on performance considerations that are simply irrelevant for
-the application.
+@i<@s8<Static Semantics>>
 
-Evaluation of existing proposals
+The library package Containers has the following declaration:
 
-We determined that the most important containers are the following:
-    * extensible "vectors" (like an array, indexed by any discrete type);
-    * (hashed) "maps" (or "hash table", with arbitrary keys);
-    * (sorted) "sets" (set of arbitrary items).
-The names "map", "set", and "vector" are those used in the Java containers.
+@xcode<@b<package> Ada.Containers @b<is>
+   @b<pragma> Pure(Containers);
 
-We evaluated the two proposals for their support of these components.
+   @b<type> Hash_Type @b<is mod> @ft<@i<implementation-defined>>;
 
-Alternative 1 (AI-302-1/07) contains a number of low level data structure
-components such as Lists, Bags, Queues, etc. These can be used to create
-"vector", "map", and "set" containers, but the containers themselves are
-absent. Moreover, most of these components are relatively easy to create
-when needed.
+   @b<type> Count_Type @b<is range> 0 .. @ft<@i<implementation-defined>>;
 
-Alternative 2 (AI-302-2/02) contains mainly five containers: vector, list,
-map, set, and multiset. These include the abstractions mentioned above. We
-also determined that the basic design was consistent and sound.
+@b<end> Ada.Containers;>
 
-Therefore, we discarded alternative 1, and concentrated on improving and
-simplifying alternative 2.
+Hash_Type represents the range of the result of a hash function. Count_Type
+represents the (potential or actual) number of elements of a container.
 
-We decided the sorts of changes that we would consider. The great value to
-having containers in the standard is that they are standard: everybody has
-them and can use them. Perfection is not required of the standard components.
-Moreover, what is one person's "improvement" is another's "mistake". In
-addition, we run the risk of introducing real errors by further fiddling.
+@i<@s8<Implementation Advice>>
 
-Therefore, we decided to simplify the interfaces by deleting unnecessary
-capabilities, by systematic substitutions, and by introducing missing
-capabilities (along with general wordsmithing). In particular, we avoided
-changing existing interfaces unless there was a clear error.
+Hash_Type'Modulus should be at least 2**32. Count_Type'Last should be at least
+2**31-1.
 
-The specific improvements and simplifications are detailed in the Appendix.
+!corrigendum A.18.2
 
-Performance issues
+@dinsc
+The language-defined generic package Containers.Vectors provides private types
+Vector and Cursor, and a set of operations for each type. A vector container
+allows insertion and deletion at any position, but it is specifically optimized
+for insertion and deletion at the high end (the end with the higher index) of
+the container. A vector container also provides random access to its elements.
+
+A vector container behaves conceptually as an array that expands as necessary
+as items are inserted. The @i<length> of a vector is the number of elements that
+the vector contains. The @i<capacity> of a vector is the maximum number of
+elements that can be inserted into the vector prior to it being automatically
+expanded.
 
-For the purposes of components in the standard, the precise performance of them
-is not important. Whatever the performance is will be good enough for the vast
-majority of uses - in prototyping, quick and dirty programs, and the majority
-of programs that aren't performance critical. Therefore, we provide only a
-single version of each component. We don't, for instance, provide both Vectors
-and Lists, which are really the same abstraction with the different performance
-characteristics.
+A vector container may contain @i<empty elements>. Empty elements do not have a
+specified value.
 
-However, it is important that the performance characteristics of the components
-be specified. That is, if searches are expected to be no worse than O(N), we
-need to say that. That's because we want programs using the components to be
-portable. That wouldn't be true for programs using components with large
-numbers of items if the performance characteristics vary widely between
-implementations. Consider a Vector component. It could in theory be implemented
-with an array or with a linked list. The cost of an arbitrary insertion is O(N)
-for the array implementation and O(1) for the list implementation. If a program
-using a large vector is moved from a list implementation to an array
-implementation, the performance change could be so large as to make the program
-non-functional. That is unacceptable, so we specify minimum performance
-characteristics. But those characteristics are not intended to specify a
-particular implementation, only to insure that some characteristics can be
-relied upon.
+@i<@s8<Static Semantics>>
 
-Therefore, the containers library needs to suggest some performance
-characteristics. We believe Implementation Advice is best for this purpose,
-as we don't have to be as precise in the language defining the characteristics,
-and implementations are required to document deviations from the given
-advice.
+The generic library package Containers.Vectors has the following declaration:
 
-Appendix
+@xcode<@b<generic>
+   @b<type> Index_Type @b<is range> <@>;
+   @b<type> Element_Type @b<is private>;
+   @b<with function> "=" (Left, Right : Element_Type)
+      @b<return> Boolean @b<is> <@>;
+@b<package> Ada.Containers.Vectors @b<is>
+   @b<pragma> Preelaborate(Vectors);
 
-Detailed changes made to the Alternative 2 proposal
+   @b<subtype> Extended_Index @b<is>
+      Index_Type'Base @b<range>
+         Index_Type'First-1 ..
+         Index_Type'Min (Index_Type'Base'Last - 1, Index_Type'Last) + 1;
+   No_Index : @b<constant> Extended_Index := Extended_Index'First;
 
-The Unchecked_Modification packages were dropped. These are just a hack to
-avoid copying keys - a solely performance-based concern. Other stuff does
-not logically belong in keys, and modifying the key value itself it a disaster
-waiting to happen.
+   @b<subtype> Index_Subtype @b<is> Index_Type;
 
-The Vector, List, and Multiset abstractions are essentially the same
-abstraction with differences in performance and details. When performance
-is not critical, only one is needed.
+   @b<type> Vector @b<is tagged private>;
 
-The package structure has many levels of empty packages for organization.
-These are unnecessary when there are only a few packages. Moreover, related
-packages can be given similar names (i.e. "Bounded_Set", "Protected_Vector"),
-which provides all of the organization needed. The extra empty packages
-were eliminated. Similarly, "Unbounded" was dropped; these are the most
-general forms, and should be the ones used for general-purpose programming.
-Other forms (in a secondary standard) would be more specialized.
+   @b<type> Cursor @b<is private>;
 
-We discussed dropping the special string maps. We eventually decided to keep
-them, because string maps are common, and a Map cannot be instantiated with
-"String" (the key type must be definite).
+   Empty_Vector : @b<constant> Vector;
 
-We also discussed whether Sets should be sorted. We concluded that the extra
-cost of sorted insertions is fairly small, and thus there is little advantage
-to using unsorted sets other than when performance is critical (which again
-is not the purpose of the standard). We did, however, name the package
-"Sorted_Sets" so that a basic unsorted set could be provided in a secondary
-standard without contorted naming.
+   No_Element : @b<constant> Cursor;
 
-We added a modular Hash_Type to Ada.Containers. The choice of Integer'Base is
-a horrible one on compilers that use 16-bit Integer (as allowed by the
-standard), and in any case, the hashing type should be modular.
+   @b<function> To_Vector (Length : Count_Type) @b<return> Vector;
 
-The string hash and comparison functions were moved to be part of the
-Ada.Strings hierarchy. It would be a bad idea to have the hash functions
-of all types gathered in one place (in the containers library).
+   @b<function> To_Vector
+     (New_Item : Element_Type;
+      Length   : Count_Type) @b<return> Vector;
 
-Unbounded string hash and comparison functions were added.
+   @b<function> "&" (Left, Right : Vector) @b<return> Vector;
 
-We changed the type names to the more descriptive "Vector_Type", "Map_Type",
-and "Set_Type". These are much better for users who use Use clauses. The
-argument that having a common name makes it easier to change between containers
-is mostly irrelevant: changing between the provided containers is going to be
-rare. Moreover, qualifying "Container_Type" (that is, "Vector.Container_Type")
-would be necessary in any unit with more than one container -- eliminating any
-advantage for using the same name.
+   @b<function> "&" (Left  : Vector;
+                 Right : Element_Type) @b<return> Vector;
 
-The proposal confused the meaning of "iterator", using it both for the
-code that visits each element of a container (the conventional meaning) and
-the "handle" or "cursor" used to access an element of a container. We decided
-to use "cursor" for the second meaning to make the interfaces clearer.
+   @b<function> "&" (Left  : Element_Type;
+                 Right : Vector) @b<return> Vector;
 
-We added a sort routine to Vector. For some reason, this was only present
-in the (removed) List abstraction. Having a simple sort available can
-simplify many programming problems.
+   @b<function> "&" (Left, Right  : Element_Type) @b<return> Vector;
 
-We added legality rules that these packages must be instantiated at the
-library level. The requirement that these packages do not
-leak memory (like Ada.Strings.Unbounded) imply that they are implemented with
-controlled types (or something like controlled types). We do not want to
-implicitly require implementers to support nested controlled types without
-making that support available to users. (If AI-344 or AC-50 were adopted, we
-could drop these rules.)
+   @b<function> "=" (Left, Right : Vector) @b<return> Boolean;
 
-The proposal was completely missing definitions for the string hash and
-compare functions.
+   @b<function> Capacity (Container : Vector) @b<return> Count_Type;
 
-Performance requirements were moved from the !proposal into Implementation
-Advice. As much as possible, mention of specific implementation strategies
-was moved into AARM notes following that Advice. (We're not going to specify
-red-black trees!).
+   @b<procedure> Reserve_Capacity (Container : @b<in out> Vector;
+                               Capacity  : @b<in>     Count_Type);
 
-An Assert pragma was added to the Vector package to prevent instantiation with
-a type for which Index_Type'Base'First = Index_Type'First. For such a type,
-the initial value of Last and the value of Front must necessarily raise
-Constraint_Error. It's better to fail an assertion immediately, rather than
-during some later operation.
+   @b<function> Length (Container : Vector) @b<return> Count_Type;
 
-The Map container in the proposal is far too specific to a particular
-implementation. It exposes that implementation in the interface, and as a
-result makes iteration operations harder. That seems like a bad choice for
-a simple abstraction; it's fine to suggest an implementation, but bad to
-make it part of the interface. We therefore simplified the interface and the
-description. (We consulted with the author of the proposal on this and other
-changes.)
+   @b<function> Is_Empty (Container : Vector) @b<return> Boolean;
 
-****************************************************************
+   @b<procedure> Clear (Container : @b<in out> Vector);
 
-From: Marius Amado Alves
-Sent: Wednesday, February 4, 2004  5:13 AM
+   @b<function> To_Cursor (Container : Vector;
+                       Index     : Extended_Index) @b<return> Cursor;
 
->Report of the ARG Select Committee on Containers
->February 3, 2004
->...
+   @b<function> To_Index (Position  : Cursor) @b<return> Extended_Index;
 
-Sorry for my poor knowledge of ARG procedure.
-Does this step mean the library is secured for Ada 2005?
-Thanks.
+   @b<function> Element (Container : Vector;
+                     Index     : Index_Type)
+      @b<return> Element_Type;
 
-****************************************************************
+   @b<function> Element (Position : Cursor) @b<return> Element_Type;
 
-From: Martin Dowie
-Sent: Wednesday, February 4, 2004  5:30 AM
+   @b<procedure> Query_Element
+     (Container : @b<in> Vector;
+      Index     : @b<in> Index_Type;
+      Process   : @b<not null access procedure> (Element : @b<in> Element_Type));
 
-> Sorry for my poor knowledge of ARG procedure.
-> Does this step mean the library is secured for Ada 2005?
-> Thanks.
+   @b<procedure> Query_Element
+     (Position : @b<in> Cursor;
+      Process  : @b<not null access procedure> (Element : @b<in> Element_Type));
 
-Nope - it's still a "Work Item", see:
+   @b<procedure> Update_Element
+     (Container : @b<in> Vector;
+      Index     : @b<in> Index_Type;
+      Process   : @b<not null access procedure> (Element : @b<in out> Element_Type));
 
-http://www.ada-auth.org/cgi-bin/cvsweb.cgi/AIs/AI-20302.TXT?rev=1.1
+   @b<procedure> Update_Element
+     (Position : @b<in> Cursor;
+      Process  : @b<not null access procedure> (Element : @b<in out> Element_Type));
 
+   @b<procedure> Replace_Element (Container : @b<in> Vector;
+                              Index     : @b<in> Index_Type;
+                              By        : @b<in> Element_Type);
 
+   @b<procedure> Replace_Element (Position : @b<in> Cursor;
+                              By       : @b<in> Element_Type);
 
-Also, in the text of the AI :-
+   @b<procedure> Assign (Target : @b<in out> Vector;
+                     Source : @b<in>     Vector);
 
-with Ada.Containers;
-package Ada.Strings.Case_Insensitive is
-    pragma Pure (Case_Insensitive);
+   @b<procedure> Move (Target : @b<in out> Vector;
+                   Source : @b<in out> Vector);
 
-    function "=" (Left, Right : String) return Boolean;
-    function "/=" (Left, Right : String) return Boolean;
-             ^^^^
-Guess this wasn't really meant.
+   @b<procedure> Insert (Container : @b<in out> Vector;
+                     Before    : @b<in>     Extended_Index;
+                     New_Item  : @b<in>     Vector);
 
-****************************************************************
+   @b<procedure> Insert (Container : @b<in out> Vector;
+                     Before    : @b<in>     Cursor;
+                     New_Item  : @b<in>     Vector);
 
-From: Martin Dowie
-Sent: Wednesday, February 4, 2004  8:11 AM
+   @b<procedure> Insert (Container : @b<in out> Vector;
+                     Before    : @b<in>     Cursor;
+                     New_Item  : @b<in>     Vector;
+                     Position  :    @b<out> Cursor);
 
-1) Couple of typos in package Ada.Containers.Maps
+   @b<procedure> Insert (Container : @b<in out> Vector;
+                     Before    : @b<in>     Extended_Index;
+                     New_Item  : @b<in>     Element_Type;
+                     Count     : @b<in>     Count_Type := 1);
 
-     generic
-        with procedure Process (Cursor : in Cursor_Type) is <>;
-     procedure Generic_Iteration (Map : in Map_Type);
+   @b<procedure> Insert (Container : @b<in out> Vector;
+                     Before    : @b<in>     Cursor;
+                     New_Item  : @b<in>     Element_Type;
+                     Count     : @b<in>     Count_Type := 1);
 
-     - description refers to 'Generic_Cursor'
+   @b<procedure> Insert (Container : @b<in out> Vector;
+                     Before    : @b<in>     Cursor;
+                     New_Item  : @b<in>     Element_Type;
+                     Position  :    @b<out> Cursor;
+                     Count     : @b<in>     Count_Type := 1);
 
-     function Length (Map : Map_Type) return Natural;
+   @b<procedure> Prepend (Container : @b<in out> Vector;
+                      New_Item  : @b<in>     Vector);
 
-     - description refers to 'Container' when it should be 'Map'
+   @b<procedure> Prepend (Container : @b<in out> Vector;
+                      New_Item  : @b<in>     Element_Type;
+                      Count     : @b<in>     Count_Type := 1);
 
-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?
+   @b<procedure> Append (Container : @b<in out> Vector;
+                     New_Item  : @b<in>     Vector);
 
-****************************************************************
+   @b<procedure> Append (Container : @b<in out> Vector;
+                     New_Item  : @b<in>     Element_Type;
+                     Count     : @b<in>     Count_Type := 1);
 
-From: Martin Dowie
-Sent: Wednesday, February 4, 2004  8:21 AM
+   @b<procedure> Insert_Space (Container : @b<in out> Vector;
+                           Before    : @b<in>     Extended_Index;
+                           Count     : @b<in>     Count_Type := 1);
 
-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.
+   @b<procedure> Insert_Space (Container : @b<in out> Vector;
+                           Before    : @b<in>     Cursor;
+                           Position  :    @b<out> Cursor;
+                           Count     : @b<in>     Count_Type := 1);
 
-Charles didn't suffer from this problem as Unbounded maps (~ACM)
-and String Maps (~ACMS) were siblings not parent/child.
+   @b<procedure> Set_Length (Container : @b<in out> Vector;
+                         Length    : @b<in>     Count_Type);
 
-****************************************************************
+   @b<procedure> Delete (Container : @b<in out> Vector;
+                     Index     : @b<in>     Extended_Index;
+                     Count     : @b<in>     Count_Type := 1);
 
-From: Matthew Heaney
-Sent: Wednesday, February 4, 2004  8:57 AM
+   @b<procedure> Delete (Container : @b<in out> Vector;
+                     Position  : @b<in out> Cursor;
+                     Count     : @b<in>     Count_Type := 1);
 
->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?
+   @b<procedure> Delete_First (Container : @b<in out> Vector;
+                           Count     : @b<in>     Count_Type := 1);
 
-Just use an active iterator.
+   @b<procedure> Delete_Last (Container : @b<in out> Vector;
+                          Count     : @b<in>     Count_Type := 1);
 
-****************************************************************
+   @b<function> First_Index (Container : Vector) @b<return> Index_Type;
 
-From: Matthew Heaney
-Sent: Wednesday, February 4, 2004  9:52 AM
+   @b<function> First (Container : Vector) @b<return> Cursor;
 
-Note that that's not really the correct mode anyway: it should be inout,
-not just out, like this:
+   @b<function> First_Element (Container : Vector)
+      @b<return> Element_Type;
 
-   generic
-      with procedure Process
-         (Cursor : in     Cursor_Type;
-           Done   : in out Boolean) is <>;
-   procedure Generic_Iteration (Map : in out Map_Type);
+   @b<function> Last_Index (Container : Vector) @b<return> Extended_Index;
 
-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.
+   @b<function> Last (Container : Vector) @b<return> Cursor;
 
-If you only want to visit some of the items, then just use an active
-iterator, and exit the loop when you need to:
+   @b<function> Last_Element (Container : Vector)
+      @b<return> Element_Type;
 
-   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;
+   @b<procedure> Swap (Container : @b<in> Vector;
+                   I, J      : @b<in> Index_Type);
 
-          Increment (I);
-      end loop;
-   end;
+   @b<procedure> Swap (I, J      : @b<in>     Cursor);
 
-****************************************************************
+   @b<generic>
+      @b<with function> "<" (Left, Right : Element_Type)
+         @b<return> Boolean @b<is> <@>;
+   @b<procedure> Generic_Sort (Container : @b<in> Vector);
 
-From: Martin Dowie
-Sent: Wednesday, February 4, 2004  10:06 AM
+   @b<function> Find_Index (Container : Vector;
+                        Item      : Element_Type;
+                        Index     : Index_Type := Index_Type'First)
+      @b<return> Extended_Index;
 
+   @b<function> Find (Container : Vector;
+                  Item      : Element_Type;
+                  Position  : Cursor := No_Element)
+      @b<return> Cursor;
 
-[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]
+   @b<function> Reverse_Find_Index (Container : Vector;
+                                Item      : Element_Type;
+                                Index     : Index_Type := Index_Type'Last)
+      @b<return> Extended_Index;
 
-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.
+   @b<function> Reverse_Find (Container : Vector;
+                          Item      : Element_Type;
+                          Position  : Cursor := No_Element)
+      @b<return> Cursor;
 
-I'd be delighted if both versions could be included! :-)
+   @b<function> Contains (Container : Vector;
+                      Item      : Element_Type) @b<return> Boolean;
 
-****************************************************************
 
-From: Matthew Heaney
-Sent: Wednesday, February 4, 2004  11:16 AM
+   @b<function> Next (Position : Cursor) @b<return> Cursor;
 
-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.
+   @b<function> Previous (Position : Cursor) @b<return> Cursor;
 
-It would be helpful if you could be specific about what kind of
-container you were using.
+   @b<procedure> Next (Position : @b<in out> Cursor);
 
-The vector has neither active nor passive iterators, which means that
-for a vector you have to use a loop anyway.
+   @b<procedure> Previous (Position : @b<in out> Cursor);
 
-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?
+   @b<function> Has_Element (Position : Cursor) @b<return> Boolean;
 
-The sorted set is the borderline case.
+   @b<procedure>  Iterate
+     (Container : @b<in> Vector;
+      Process   : @b<not null access procedure> (Position : @b<in> Cursor));
 
-****************************************************************
+   @b<procedure> Reverse_Iterate
+     (Container : @b<in> Vector;
+      Process   : @b<not null access procedure> (Position : @b<in> Cursor));
 
-From: Peter Hermann
-Sent: Wednesday, February 4, 2004  5:57 AM
+@b<private>
 
-> package Ada.Strings.Case_Insensitive is
+   ... -- @ft<@i<not specified by the language>>
 
-indeed useful.
-expected to be overloaded for fixed and (un)bounded strings.
+@b<end> Ada.Containers.Vectors;>
 
-****************************************************************
 
-From: Matthew Heaney
-Sent: Wednesday, February 4, 2004  9:02 AM
+The type Vector is used to represent vectors. The type Vector needs finalization
+(see 7.6).
 
->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.
+Empty_Vector represents the empty vector object. It has a length of 0. If an
+object of type Vector is not otherwise initialized, it is initialized to the
+same value as Empty_Vector.
 
-That's definitely a bug in the report.  The string-key map is not a
-child of a generic.  Maybe we should do this:
+No_Element represents a cursor that designates no element. If an object of type
+Cursor is not otherwise initialized, it is initialized to the same value as
+No_Element.
 
-package Ada.Containers.Maps
-package Ada.Containers.String_Maps
+No_Index represents a position that does not correspond to any element. The
+subtype Extended_Index includes the indices covered by Index_Type plus the
+value No_Index and, if it exists, the successor to the Index_Type'Last.
 
-****************************************************************
+Some operations are assumed to work on a constant set of elements. For such
+an operation, a subprogram is said to @i<tamper with cursors> of a vector
+object @i<V> if:
 
-From: Marius Amado Alves
-Sent: Wednesday, February 4, 2004  9:07 AM
+@xbullet<it inserts or deletes elements of @i<V>, that is, it calls the Insert,
+Insert_Space, Clear, Delete, or Set_Length procedures with @i<V> as a
+parameter; or>
 
-Yes, please change that. There is a steady requirement that a single
-instantiation must be enough to get a container.
+@xbullet<it finalizes @i<V>; or>
 
-****************************************************************
+@xbullet<it calls the Move procedure with @i<V> as
+a parameter.>
 
-From: Pascal Obry
-Sent: Wednesday, February 4, 2004 10:10 AM
+Some operations are assumed to not change elements.  For such an operation, a
+subprogram is said to @i<tamper with elements> of a vector object @i<V> if:
 
-> 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.
+@xbullet<it tampers with cursors of @i<V>; or>
+@xbullet<it modifies one or more elements of @i<V>, that is, it calls the
+Replace_Element, Update_Element, or Swap procedures or an
+instance of Generic_Sort with @i<V> as a parameter.>
 
-Agreed, this is the way iterators are designed in the POSIX 1003.5 standard
-for example.
+@xcode<@b<function> To_Vector (Length : Count_Type) @b<return> Vector;>
 
-****************************************************************
+@xindent<Returns a vector with a length of Length, filled with empty elements.>
 
-From: Marius Amado Alves
-Sent: Wednesday, February 4, 2004  9:02 AM
+@xcode<@b<function> To_Vector
+  (New_Item : Element_Type;
+   Length   : Count_Type) @b<return> Vector;>
 
-> 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?
+@xindent<Returns a vector with a length of Length, filled with elements initialized to
+the value New_Item.>
 
-Indeed some people ban the use of exceptions for control flow. I guess they
-are not a majority in the committee. Fortunately ;-)
+@xcode<@b<function> "&" (Left, Right : Vector) @b<return> Vector;>
 
-/* 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. */
+@xindent<Returns a vector comprising the elements of Left followed by the
+elements of Right.>
 
-****************************************************************
+@xcode<@b<function> "&" (Left  : Vector;
+              Right : Element_Type) @b<return> Vector;>
 
-From: Randy Brukardt
-Sent: Wednesday, February 4, 2004  8:55 PM
+@xindent<Returns a vector comprising the elements of Left followed by the
+element Right.>
 
-Marius Amado Alves wrote:
+@xcode<@b<function> "&" (Left  : Element_Type;
+              Right : Vector) @b<return> Vector;>
 
-> Sorry for my poor knowledge of ARG procedure.
-> Does this step mean the library is secured for Ada 2005?
+@xindent<Returns a vector comprising the element Left followed by the elements of Right.>
 
-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).
+@xcode<@b<function> "&" (Left, Right  : Element_Type) @b<return> Vector;>
 
-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.
+@xindent<Returns a vector comprising the element Left followed by the element Right.>
 
-Martin Dowie wrote:
+@xcode<@b<function> "=" (Left, Right : Vector) @b<return> Boolean;>
 
-> 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.
+@xindent<If Left and Right denote the same vector object, then the function returns
+True. If Left and Right have different lengths, then the function returns
+False. Otherwise, it compares each element in Left to the corresponding element
+in Right using the generic formal equality operator; if element equality
+returns False, then the function returns False. If the function has not
+returned a result after checking all of the elements, it returns True. Any
+exception raised during evaluation of element equality is propagated.>
 
-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.)
+@xcode<@b<function> Capacity (Container : Vector) @b<return> Count_Type;>
 
-And later, replying to Matt:
+@xindent<Returns the capacity of Container.>
 
->[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]
+@xcode<@b<procedure> Reserve_Capacity (Container : @b<in out> Vector;
+                            Capacity  : @b<in>     Count_Type);>
 
->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.
+@xindent<Reserve_Capacity allocates new internal data structures such that the length of
+the resulting vector can become at least the value Capacity without requiring
+an additional call to Reserve_Capacity, and is large enough to hold the current
+length of Container. Reserve_Capacity then copies the elements into the new
+data structures and deallocates the old data structures. Any exception raised
+during allocation is propagated and Container is not modified.>
 
-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!)
+@xcode<@b<function> Length (Container : Vector) @b<return> Count_Type;>
 
-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:
+@xindent<Returns the number of elements in Container.>
 
-    for I in First(Vect) .. Last(Vect) loop
-        -- Do whatever.
-    end loop;
+@xcode<@b<function> Is_Empty (Container : Vector) @b<return> Boolean;>
 
-versus
+@xindent<Equivalent to Length (Container) = 0.>
 
-    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;
+@xcode<@b<procedure> Clear (Container : @b<in out> Vector);>
 
-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.
+@xindent<Removes all the elements from Container. The capacity of Container does not
+change.>
 
-Marius Amado Alves wrote:
+@xcode<@b<function> To_Cursor (Container : Vector;
+                    Index     : Extended_Index) @b<return> Cursor;>
 
-> /* 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. */
+@xindent<If Index is not in the range First_Index (Container) .. Last_Index (Container),
+then No_Element is returned. Otherwise, a cursor designating the
+element at position Index in Container is returned.>
 
-The wording for Generic_Iteration for a Map says:
+@xcode<@b<function> To_Index (Position  : Cursor) @b<return> Extended_Index;>
 
-Generic_Iteration calls Process with a cursor that designates each
-node in the Map. Any exceptions raised during Process are propagated.
+@xindent<If Position is No_Element, No_Index is returned. Otherwise, the
+index (within its containing vector) of the element designated by Cursor is
+returned.>
 
-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.
+@xcode<@b<function> Element (Container : Vector;
+                  Index     : Index_Type)
+   @b<return> Element_Type;>
 
-****************************************************************
+@xindent<If Index is not in the range First_Index (Container) .. Last_Index (Container),
+then Constraint_Error is propagated. Otherwise, Element returns the element at
+position Index.>
+
+@xcode<@b<function> Element (Position  : Cursor) @b<return> Element_Type;>
+
+@xindent<If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
+Element returns the element designated by Position.>
+
+@xcode<@b<procedure> Query_Element
+  (Container : @b<in> Vector;
+   Index     : @b<in> Index_Type;
+   Process   : @b<not null access> @b<procedure> (Element : @b<in> Element_Type));>
+
+@xindent<If Index is not in the range First_Index (Container) .. Last_Index (Container),
+then Constraint_Error is propagated. Otherwise, Query_Element calls Process.all
+with the element at position Index as the argument. Program_Error is propagated
+if Process.all tampers with the elements of Container. Any exception raised by
+Process.all is propagated.>
+
+@xcode<@b<procedure> Query_Element
+  (Position : @b<in> Cursor;
+   Process  : @b<not null access> @b<procedure> (Element : @b<in> Element_Type));>
+
+@xindent<If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
+Query_Element calls Process.@b<all> with the element designated by Position as the
+argument. Program_Error is propagated if Process.@b<all> tampers with the
+elements of Container. Any exception raised by Process.@b<all> is propagated.>
+
+@xcode<@b<procedure> Update_Element
+  (Container : @b<in> Vector;
+   Index     : @b<in> Index_Type;
+   Process   : @b<not null access> @b<procedure> (Element : @b<in out> Element_Type));>
+
+@xindent<If Index is not in the range First_Index (Container) .. Last_Index (Container),
+then Constraint_Error is propagated. Otherwise, Update_Element calls Process.@b<all>
+with the element at position Index as the argument. Program_Error is propagated
+if Process.@b<all> tampers with the elements of Container. Any exception raised by
+Process.@b<all> is propagated.>
+
+@xindent<If Element_Type is unconstrained and definite, then the Element parameter
+of Process.@b<all> shall be unconstrained.>
+
+@xindent<The element at position Index is not an empty element after successful
+completion of this operation.>
+
+@xcode<@b<procedure> Update_Element
+  (Position : @b<in> Cursor;
+   Process  : @b<not null access> @b<procedure> (Element : @b<in out> Element_Type));>
+
+@xindent<If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
+Update_Element calls Process.@b<all> with the element designated by Position as the
+argument. Program_Error is propagated if Process.@b<all> tampers with the
+elements of Container. Any exception raised by Process.@b<all> is propagated.>
+
+@xindent<If Element_Type is unconstrained and definite, then the Element parameter
+of Process.@b<all> shall be unconstrained.>
+
+@xindent<The element designated by Position is not an empty element after successful
+completion of this operation.>
+
+@xcode<@b<procedure> Replace_Element (Container : @b<in> Vector;
+                           Index     : @b<in> Index_Type;
+                           By        : @b<in> Element_Type);>
+
+@xindent<If Index is not in the range First_Index (Container) .. Last_Index (Container),
+then Constraint_Error is propagated. Otherwise Replace_Element assigns the
+value By to the element at position Index. Any exception raised during the
+assignment is propagated. The element at position Index is not an empty element
+after successful call to Replace_Element.>
+
+@xcode<@b<procedure> Replace_Element (Position : @b<in> Cursor;
+                           By       : @b<in> Element_Type);>
+
+@xindent<If Position equals No_Element, then Constraint_Error is propagated. Otherwise
+Replace_Element assigns By to the element designated by Position. Any exception
+raised during the assignment is propagated. The element at Position is
+not an empty element after successful call to Replace_Element.>
+
+@xcode<@b<procedure> Assign (Target : @b<in out> Vector;
+                  Source : @b<in>     Vector);>
+
+@xindent<If Target denotes the same object as Source, then the operation has no effect.
+Otherwise, Assign first calls Clear (Target), then Reserve_Capacity (Target,
+Length (Source)). It then assigns the elements of Source to the corresponding
+positions in Target, and sets the length of Target to the length of Source.
+Any exception raised during element assignment is propagated.>
+
+@xcode<@b<procedure> Move (Target : @b<in out> Vector;
+                Source : @b<in out> Vector);>
+
+@xindent<If Target denotes the same object as Source, then Move has no effect.
+Otherwise, Move first calls Clear (Target); then, each element from Source
+is removed from Source and inserted into Target in the original order. The
+length of Source is 0 after a successful call to Move.>
+
+@xcode<@b<procedure> Insert (Container : @b<in out> Vector;
+                  Before    : @b<in>     Extended_Index;
+                  New_Item  : @b<in>     Vector);>
+
+@xindent<If Before is not in the range First_Index (Container) ..
+Last_Index (Container) + 1, then Constraint_Error is propagated. If
+Length(New_Item) is 0, then Insert does nothing. Otherwise, it computes the new
+length @i<NL> as the sum of the current length and Length (New_Item); if the
+value of Last appropriate for length @i<NL> would be greater than Index_Type'Last
+then Constraint_Error is propagated.>
+
+@xindent<If the current vector capacity is less than or equal to @i<NL>,
+Reserve_Capacity (Container, @i<NL>) is called to increase the vector capacity.
+Then Insert slides the elements in the range Before .. Last_Index (Container)
+up by Length(New_Item) positions, and then copies the elements of New_Item to
+the positions starting at Before. Any exception raised during the copying is
+propagated.>
+
+@xcode<@b<procedure> Insert (Container : @b<in out> Vector;
+                  Before    : @b<in>     Cursor;
+                  New_Item  : @b<in>     Vector);>
+
+@xindent<Program_Error is propagated unless Before is equal to No_Element or
+designated an element in Target. Otherwise, if Length(New_Item) is 0,
+then Insert does nothing.
+If Before is No_Element, then the call is equivalent to Insert (Container,
+Last_Index (Container) + 1), New_Item); otherwise the call is
+equivalent to Insert (Container, To_Index (Before), New_Item);>
+
+@xcode<@b<procedure> Insert (Container : @b<in out> Vector;
+                  Before    : @b<in>     Cursor;
+                  New_Item  : @b<in>     Vector;
+                  Position  :    @b<out> Cursor);>
+
+@xindent<Program_Error is propagated unless Before is equal to No_Element or
+designated an element in Target.
+If Before equals No_Element, then
+let @i<T> be Last_Index (Container) + 1; otherwise, let @i<T> be
+To_Index (Before). Insert (Container, @i<T>, New_Item) is called, and then
+Position is set to To_Cursor (Container, @i<T>).>
+
+@xcode<@b<procedure> Insert (Container : @b<in out> Vector;
+                  Before    : @b<in>     Extended_Index;
+                  New_Item  : @b<in>     Element_Type;
+                  Count     : @b<in>     Count_Type := 1);>
+
+@xindent<Equivalent to Insert (Container, Before, To_Vector (New_Item, Count));>
+
+@xcode<@b<procedure> Insert (Container : @b<in out> Vector;
+                  Before    : @b<in>     Cursor;
+                  New_Item  : @b<in>     Element_Type;
+                  Count     : @b<in>     Count_Type := 1);>
+
+@xindent<Equivalent to Insert (Container, Before, To_Vector (New_Item, Count));>
+
+@xcode<@b<procedure> Insert (Container : @b<in out> Vector;
+                  Before    : @b<in>     Cursor;
+                  New_Item  : @b<in>     Element_Type;
+                  Position  :    @b<out> Cursor;
+                  Count     : @b<in>     Count_Type := 1);>
+
+@xindent<Equivalent to Insert (Container, Before, To_Vector (New_Item, Count), Position);>
+
+@xcode<@b<procedure> Prepend (Container : @b<in out> Vector;
+                   New_Item  : @b<in>     Vector;
+                   Count     : @b<in>     Count_Type := 1);>
+
+@xindent<Equivalent to Insert (Container, Index_Type'First, New_Item).>
+
+@xcode<@b<procedure> Prepend (Container : @b<in out> Vector;
+                   New_Item  : @b<in>     Element_Type;
+                   Count     : @b<in>     Count_Type := 1);>
+
+@xindent<Equivalent to Insert (Container, Index_Type'First, New_Item, Count).>
+
+@xcode<@b<procedure> Append (Container : @b<in out> Vector;
+                  New_Item  : @b<in>     Vector);>
+
+@xindent<Equivalent to Insert (Container, Last_Index (Container) + 1, New_Item).>
+
+@xcode<@b<procedure> Append (Container : @b<in out> Vector;
+                  New_Item  : @b<in>     Element_Type;
+                  Count     : @b<in>     Count_Type := 1);>
+
+@xindent<Equivalent to Insert (Container, Last_Index (Container) + 1, New_Item, Count).>
+
+@xcode<@b<procedure> Insert_Space (Container : @b<in out> Vector;
+                        Before    : @b<in>     Extended_Index;
+                        Count     : @b<in>     Count_Type := 1);>
+
+@xindent<If Before is not in the range First_Index (Container) .. Last_Index (Container)
++ 1, then Constraint_Error is propagated. If Count is 0, then Insert_Space does
+nothing. Otherwise, it computes the new length @i<NL> as the sum of the current
+length and Count; if the value of Last appropriate for length @i<NL> would be
+greater than Index_Type'Last then Constraint_Error is propagated.>
+
+@xindent<If the current vector capacity is less than or equal to @i<NL>,
+Reserve_Capacity (Container, @i<NL>) is called to increase the vector capacity.
+Then Insert_Space slides the elements in the range Before .. Last_Index
+(Container) up by Count positions, and then inserts empty elements in the
+positions starting at Before.>
+
+@xcode<@b<procedure> Insert_Space (Container : @b<in out> Vector;
+                        Before    : @b<in>     Cursor;
+                        Position  :    @b<out> Cursor;
+                        Count     : @b<in>     Count_Type := 1);>
+
+@xindent<Program_Error is propagated unless Before is equal to No_Element or
+designated an element in Target.
+If Before equals No_Element, then let @i<T> be Last_Index (Container) + 1;
+otherwise, let @i<T> be To_Index (Before). Insert_Space (Container, @i<T>, Count) is
+called, and then Position is set to To_Cursor (Container, @i<T>).>
 
-From: Jeffrey Carter
-Sent: Wednesday, February 4, 2004  8:53 PM
+@xcode<@b<procedure> Set_Length (Container : @b<in out> Vector;
+                      Length    : @b<in>     Count_Type);>
 
-AI-302-03 asks
+@xindent<If Length is larger than the capacity of Container, Set_Length calls
+Reserve_Capacity (Container, Length), then sets the length of the
+Container to Length. If Length is greater than the original length of
+Container, empty elements are added to Container; otherwise elements are
+are removed from Container.>
 
-> Anybody got better wording [for the quality of the String hashing
-> function]? Matt was nice enough to ignore these definitions
-> completely!
+@xcode<@b<procedure> Delete (Container : @b<in out> Vector;
+                  Index     : @b<in>     Extended_Index;
+                  Count     : @b<in>     Count_Type := 1);>
+
+@xindent<If Index is not in the range First_Index (Container) .. Last_Index (Container),
+then Constraint_Error is propagated. If Count is 0, Delete has no effect.
+Otherwise Delete slides the elements (if any) starting at position Index +
+Count down to Index. Any exception raised during element assignment is
+propagated.>
+
+@xcode<@b<procedure> Delete (Container : @b<in out> Vector;
+                  Position  : @b<in out> Cursor;
+                  Count     : @b<in>     Count_Type := 1);>
 
-See
+@xindent<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, Delete (Container, To_Index (Position), Count) is called.>
 
-P. K. Pearson, "Fast Hashing of Variable-Length Text Strings," Comm.
-ACM, 1990 Jun
+@xcode<@b<procedure> Delete_First (Container : @b<in out> Vector;
+                        Count     : @b<in>     Count_Type := 1);>
 
-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".
+@xindent<Equivalent to Delete (Container, Index_Type'First, Count).>
 
-The actual algorithm produces 8-bit hash values, which may no longer be
-considered adequate, given
+@xcode<@b<procedure> Delete_Last (Container : @b<in out> Vector;
+                       Count     : @b<in>     Count_Type := 1);>
 
-> Hash_Type'Modulus shall be at least as large as the smaller of
-> System.Max_Binary_Modulus and 2**32.
+@xindent<If Length (Container) <= Count then Delete_Last is equivalent to
+Clear (Container). Otherwise it is equivalent to Delete (Container,
+Index_Type'Val(Index_Type'Pos(Last_Index(Container)) - Count + 1), Count).>
 
-I have some comments on the proposal:
+@xcode<@b<function> First_Index (Container : Vector) @b<return> Index_Type;>
 
-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.
+@xindent<Returns the value Index_Type'First.>
 
-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.
+@xcode<@b<function> First (Container : Vector) @b<return> Cursor;>
 
-Maps and sets also specify a specific implementation.
+@xindent<If Container is empty, First returns No_Element. Otherwise, it returns a cursor
+that designates the first element in Container.>
 
-If the intention is to have an extensible array structure, then I
-suggest that they be called Extensible_Arrays.
+@xcode<@b<function> First_Element (Container : Vector) @b<return> Element_Type;>
 
-Vector should have an iterator, in addition to allowing the user to
-explicitly iterate over the structure.
+@xindent<Equivalent to Element (Container, First_Index (Container)).>
 
-> 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.
+@xcode<@b<function> Last_Index (Container : Vector) @b<return> Extended_Index;>
 
-I'd say that it should be a constant, not a function. The same seems to
-hold for First.
+@xindent<If Container is empty, Last_Index returns No_Index. Otherwise, it returns the
+position of the last element in Container.>
 
-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.
+@xcode<@b<function> Last (Container : Vector) @b<return> Cursor;>
 
-All the problems with Index_Type disappear with a general list, which
-would use a cursor.
+@xindent<If Container is empty, Last returns No_Element. Otherwise, it returns a cursor
+that designates the last element in Container.>
 
-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.
+@xcode<@b<function> Last_Element (Container : Vector) @b<return> Element_Type;>
 
-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.
+@xindent<Equivalent to Element (Container, Last_Index (Container)).>
 
-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.)
+@xcode<@b<procedure> Swap (Container : @b<in> Vector;
+                I, J      : @b<in> Index_Type);>
 
-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?
+@xindent<If I or J is not in the range First_Index (Container) .. Last_Index (Container),
+then Constraint_Error is propagated. Otherwise, Swap exchanges the values of
+the elements at positions I and J.>
 
-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.
+@xcode<@b<procedure> Swap (I, J      : @b<in> Cursor);>
 
-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.
+@xindent<If either I or J is No_Element, then Constraint_Error is propagated. If I and J
+designate elements in different containers, then Program_Error is propagated.
+Otherwise Swap exchanges the values of the elements designated by I and J.>
 
-"Sans" is a French word. Since the ARM is in English, we should use the
-English "without" instead. "No" might also be acceptable.
+@xcode<@b<generic>
+   @b<with function> "<" (Left, Right : Element_Type) @b<return> Boolean is <@>;
+@b<procedure> Generic_Sort (Container : @b<in> Vector);>
 
-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.
+@xindent<Reorders the elements of Container such that the elements are
+sorted smallest first as determined by the generic formal "<" operator
+provided. Any exception raised during evalution of "<" is propagated.>
 
-****************************************************************
+@xcode<@b<function> Find_Index (Container : Vector;
+                     Item      : Element_Type;
+                     Index     : Index_Type := Index_Type'First)
+   @b<return> Extended_Index;>
 
-From: Tucker Taft
-Sent: Wednesday, February 4, 2004  9:24 PM
+@xindent<Searches the elements of Container for an element equal to Item (in the sense
+of the generic formal equality operator). The search starts at position Index
+and proceeds towards Last_Index (Container). If no equal element is found, then
+Find_Index returns No_Index. Otherwise, it returns the index of the first equal
+element encountered.>
 
-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.
+@xcode<@b<function> Find (Container : Vector;
+               Item      : Element_Type;
+               Position  : Cursor := No_Element)
+   @b<return> Cursor;>
 
-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).
+@xindent<If Position is not No_Element, and does not designate an element in Container,
+then Program_Error is propagated. Otherwise Find searches the elements of
+Container for an element equal to Item (in the sense of the generic formal
+equality operator). The search starts at the first element if Cursor equals
+No_Element, and at the element designated by Cursor otherwise. It proceeds
+towards the last element of Container. If no equal element is found, then
+Find returns No_Cursor. Otherwise, it returns a cursor designating the first
+equal element encountered.>
 
-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.
+@xcode<@b<function> Reverse_Find_Index (Container : Vector;
+                             Item      : Element_Type;
+                             Index     : Index_Type := Index_Type'Last)
+   @b<return> Extended_Index;>
 
-****************************************************************
+@xindent<Searches the elements of Container for an element equal to Item (in the sense
+of the generic formal equality operator). The search starts at position Index
+or, if Index is greater than Last_Index (Container), at position Last_Index
+(Container). It proceeds towards First_Index (Container). If no equal element
+is found, then Reverse_Find_Index returns No_Index. Otherwise, it returns the
+index of the first equal element encountered.>
 
-From: Randy Brukardt
-Sent: Wednesday, February 4, 2004  9:29 PM
+@xcode<@b<function> Reverse_Find (Container : Vector;
+                       Item      : Element_Type;
+                       Position  : Cursor := No_Element)
+   @b<return> Cursor;>
 
-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.
+@xindent<If Position is not No_Element, and does not designate an element in Container,
+then Program_Error is propagated. Otherwise Reverse_Find searches the elements
+of Container for an element equal to Item (in the sense of the generic formal
+equality operator). The search starts at the last element if Cursor equals
+No_Element, and at the element designated by Cursor otherwise. It proceeds
+towards the first element of Container. If no equal element is found, then
+Reverse_Find returns No_Cursor. Otherwise, it returns a cursor designating
+the first equal element encountered.>
 
-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.
+@xcode<@b<function> Contains (Container : Vector;
+                   Item      : Element_Type) @b<return> Boolean;>
 
-****************************************************************
+@xindent<Equivalent to Has_Element (Find (Container, Item)).>
 
-From: Randy Brukardt
-Sent: Wednesday, February 4, 2004  9:39 PM
+@xcode<@b<function> Next (Position : Cursor) @b<return> Cursor;>
 
-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.
+@xindent<If Position equals No_Element or designates the last element of the container,
+then Next returns the value No_Element. Otherwise, returns a cursor that
+designates the element with index To_Index (Position) + 1 in the same vector as
+Position.>
 
-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.
+@xcode<@b<function> Previous (Position : Cursor) @b<return> Cursor;>
 
-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!
+@xindent<If Position equals No_Element or designates the first element of the container,
+then Previous returns the value No_Element. Otherwise, returns a cursor that
+designates the element with index (To_Index (Position) - 1) in the same vector
+as Position.>
 
-> 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.
+@xcode<@b<procedure> Next (Position : @b<in out> Cursor);>
 
-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.
+@xindent<Equivalent to Position := Next (Position).>
 
-If we want an array sort, we should declare one:
+@xcode<@b<procedure> Previous (Position : @b<in out> Cursor);>
 
-    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);
+@xindent<Equivalent to Position := Previous (Position).>
 
-(We'd need an unconstrained version, too.) But keep it separate from the
-Vector one (or any List one, for that matter).
+@xcode<@b<function> Has_Element (Position : Cursor) @b<return> Boolean;>
 
-****************************************************************
+@xindent<Returns True if Position designates an element, and returns False otherwise.>
 
-From: Matthew Heaney
-Sent: Thursday, February 5, 2004  9:31 AM
+@xcode<@b<procedure> Iterate
+  (Container : @b<in> Vector;
+   Process   : @b<not null access> @b<procedure> (Position : @b<in> Cursor));>
 
-I have hosted a reference implementation at my Earthlink home page:
+@xindent<Invokes Process.@b<all> with a cursor that designates each element in Container, in
+index order. Program_Error is propagated if Process.@b<all> tampers with the
+cursors of Container. Any exception raised by Process is propagated.>
 
-<http://home.earthlink.net/~matthewjheaney/charles/ai302-20040205.zip>
+@xcode<@b<procedure> Reverse_Iterate
+  (Container : @b<in> Vector;
+   Process   : @b<not null access> @b<procedure> (Position : @b<in> Cursor));>
 
-For now it only includes the vector.  There's a test_sort program in
-there too, so you have something you can run.
+@xindent<Iterates over the nodes in Container as per Iterate, except that elements are
+traversed in reverse index order.>
 
-I'll have the set and maps done in a few days.
+@i<@s8<Bounded (Run-Time) Errors>>
 
-****************************************************************
+Reading the value of an empty element by calling Element, Query_Element,
+Update_Element, Generic_Sort, "=", Find, or Reverse_Find is a bounded error.
+The implementation may treat the element as having any valid value of the
+element type, or raise Constraint_Error or Program_Error before modifying the
+vector.
 
-From: Robart A. Duff
-Sent: Thursday, February 5, 2004  10:13 AM
+A Cursor value is @i<ambiguous> if any of the following have occurred since it
+was created:
 
-Thanks, Matt!
+@xbullet<Insert, Insert_Space, or Delete has been called on the vector that
+contains the element the
+cursor designates with an index value (or a cursor designating an element at
+such an index value) less than or equal to the index value of the element
+designated by the cursor;>
+@xbullet<The vector that contains the element it designates has been passed
+to an instance of Generic_Sort.>
 
-****************************************************************
+It is a bounded error to call any subprogram other than "=" or Has_Element
+declared in Containers.Vectors with an ambiguous (but not invalid, see below)
+cursor parameter. Possible results are:
 
-From: Jeffery Carter
-Sent: Thursday, February 5, 2004  10:58 AM
+@xbullet<The cursor may be treated as if it was No_Element;>
+@xbullet<The cursor may designate some element in the vector (but not
+necessarily the element that it originally designated);>
+@xbullet<Constraint_Error may be raised; or>
+@xbullet<Program_Error may be raised.>
 
-Randy Brukardt wrote:
+@i<@s8<Erroneous Execution>>
 
-> 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.
+A Cursor value is @i<invalid> if any of the following have occurred since it
+was created:
 
-The normative text for vectors says
+@xbullet<The vector that contains the element it designates has been finalized;>
+@xbullet<The vector that contains the element it designates has been used as
+the Source or Target of a call to Move;>
+@xbullet<The element it designates has been deleted.>
 
-"A vector container object manages an unconstrained internal array"
+The result of "=" or Has_Element is unspecified if it is called with an
+invalid cursor parameter. Execution is erroneous if any other subprogram
+declared in Containers.Vectors is called with an invalid cursor parameter.
 
-That specifies an array implementation.
+@i<@s8<Implementation Requirements>>
 
-> 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.
+No storage associated with a vector object shall be lost upon assignment or
+scope exit.
 
-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.
+@i<@s8<Implementation Advice>>
 
-> 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).
+Containers.Vectors should be implemented similarly to an array. In particular,
+if the length of a vector is @i<N>, then
 
-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.
+@xbullet<the worst-case time complexity of Append with Count=1 and Element
+should be O(log @i<N>);>
+@xbullet<the worst-case time complexity of Prepend with Count=1 or Delete_First
+with Count=1 of the vector should be O(@i<N> log @i<N>).>
 
-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.
+The worst-case time complexity of a call on an instantiation of
+Containers.Vectors.Generic_Sort should be O(@i<N>**2), and
+the average time complexity should be better than O(@i<N>**2).
 
-****************************************************************
+Containers.Vectors.Generic_Sort should minimize copying of elements.
 
-From: Randy Brukardt
-Sent: Thursday, February 5, 2004  3:23 PM
+Move should not copy elements, and should minimize copying of internal
+data structures.
 
-Jeff Carter wrote:
+@xindent<@s9<NOTES:@hr
+41 All elements of a vector occupy locations in the internal array.
+If a sparse container is required, a Hashed_Map should be used rather than a
+vector.
+@hr
+42 If Index_Type'Base'First = Index_Type'First an instantiation of
+Ada.Containers.Vectors will raise Constraint_Error. A value below
+Index_Type'First is required so that an empty vector has a meaningful
+value of Last_Index.>>
 
-> The normative text for vectors says
->
-> "A vector container object manages an unconstrained internal array"
->
-> That specifies an array implementation.
+!corrigendum A.18.3
 
-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.
+@dinsc
 
-...
-> 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.
+The language-defined generic package Containers.Doubly_Linked_Lists provides
+private types List and Cursor, and a set of operations for each type. A
+list container is optimized for insertion and deletion at any position.
 
-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.
+A doubly-linked list container object manages a linked list of internal
+@i<nodes>, each of which contains an element and pointers to the
+next (successor) and previous (predecessor) internal nodes. A cursor
+designates a particular node within a list (and by extension the element
+contained in that node). A cursor keeps designating the same node (and element)
+as long as the node is part of the container, even if the node is moved in the
+container.
 
-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.
+The @i<length> of a list is the number of elements it contains.
 
-****************************************************************
+@i<@s8<Static Semantics>>
 
-From: Matthew Heaney
-Sent: Thursday, February 5, 2004  3:40 PM
+The generic library package Containers.Doubly_Linked_Lists has the following
+declaration:
 
-Randy Brukardt wrote:
+@xcode<@b<generic>
+   @b<type> Element_Type @b<is private>;
+   @b<with function> "=" (Left, Right : Element_Type) @b<return> Boolean @b<is> <@>;
+@b<package> Ada.Containers.Doubly_Linked_Lists @b<is>
+   @b<pragma> Preelaborate (Doubly_Linked_Lists);
 
-> Precisely my point. That is intended to say that there is a logical array in
-> the container, but not necessarly an actual one.
+   @b<type> List @b<is tagged private>;
 
-Yes, exactly.  This allows the implementor to leave the type system in
-order choose the optimal implementation for the vector container.
+   @b<type> Cursor @b<is private>;
 
-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.
+   Empty_List : @b<constant> List;
 
-****************************************************************
+   No_Element : @b<constant> Cursor;
 
-From: Jeffrey Carter
-Sent: Thursday, February 5, 2004  6:52 PM
+   @b<function> "=" (Left, Right : List) @b<return> Boolean;
 
-Randy Brukardt wrote:
+   @b<function> Length (Container : List) @b<return> Natural;
 
->>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.
+   @b<function> Is_Empty (Container : List) @b<return> Boolean;
 
-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.
+   @b<procedure> Clear (Container : @b<in out> List);
 
-> 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.
+   @b<function> Element (Position : Cursor)
+      @b<return> Element_Type;
 
-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.
+   @b<procedure> Query_Element
+     (Position : @b<in> Cursor;
+      Process  : @b<not null access procedure> (Element : @b<in> Element_Type));
 
-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.
+   @b<procedure> Update_Element
+     (Position : @b<in> Cursor;
+      Process  : @b<not null access procedure> (Element : @b<in out> Element_Type));
 
-****************************************************************
+   @b<procedure> Replace_Element (Position : @b<in> Cursor;
+                              By       : @b<in> Element_Type);
 
-From: Jeffrey Carter
-Sent: Thursday, February 5, 2004  11:38 AM
+   @b<procedure> Move (Target : @b<in out> List;
+                   Source : @b<in out> List);
 
-Tucker Taft wrote:
+   @b<procedure> Prepend (Container : @b<in out> List;
+                      New_Item  : @b<in>     Element_Type;
+                      Count     : @b<in>     Count_Type := 1);
 
-> 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.
+   @b<procedure> Append (Container : @b<in out> List;
+                     New_Item  : @b<in>     Element_Type;
+                     Count     : @b<in>     Count_Type := 1);
 
-I disagree, even though I know that's dangerous when discussing Ada with
-STT. An application that uses both extensible arrays and mathematical
-vectors will be very confusing if both are called vectors. Since an
-explicit design goal of Ada is to emphasize ease of reading, calling an
-extensible array a vector seems inappropriate.
+   @b<procedure> Insert (Container : @b<in out> List;
+                     Before    : @b<in>     Cursor;
+                     New_Item  : @b<in>     Element_Type;
+                     Count     : @b<in>     Count_Type := 1);
 
-> 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).
+   @b<procedure> Insert (Container : @b<in out> List;
+                     Before    : @b<in>     Cursor;
+                     New_Item  : @b<in>     Element_Type;
+                     Position  :    @b<out> Cursor;
+                     Count     : @b<in>     Count_Type := 1);
 
-I have no objections to an extensible array, provided it's clearly
-identified as such. I think it should look different from the proposal,
-but that's mainly a taste issue. I'd want direct analogs to indexing,
-both LHS and RHS (Put and Get?); slices, both LHS and RHS (Replace_Slice
-and Slice?); and 'First, 'Last, and 'Length (though 'First is a constant
-for an EA). An equivalent to 'range would be nice, but impossible. The
-only difference to a normal array would be that Put and Replace_Slice
-can accept indices not in First .. Last. I haven't given it a great deal
-of thought, so I'm sure I'm missing some subtleties, but I don't see a
-need for Front, Back, Insert, Delete, and so on.
+   @b<procedure> Insert (Container : @b<in out> List;
+                     Before    : @b<in>     Cursor;
+                     Position  :    @b<out> Cursor;
+                     Count     : @b<in>     Count_Type := 1);
 
-The proposal says that containers "that are relatively easy to code,
-redundant, or rarely used are omitted". It also says that lists are
-difficult to implement correctly. Given a list, structures such as
-deques, stacks, and especially queues are easy to implement. Since
-queues are common structures and not redundant (none of the proposed
-containers provides an efficient implementation of a queue), the
-proposal itself seems to argue that lists should be provided, since they
-are not easy to code correctly, and provide a basis for the user to
-easily code queues.
+   @b<procedure> Delete (Container : @b<in out> List;
+                     Position  : @b<in out> Cursor;
+                     Count     : @b<in>     Count_Type := 1);
 
-> 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.
+   @b<procedure> Delete_First (Container : @b<in out> List;
+                           Count     : @b<in>     Count_Type := 1);
 
-There was an article by Mills [Harlan D. Mills, Richard C. Linger: Data
-Structured Programming: Program Design without Arrays and Pointers. IEEE
-Trans. Software Eng. 12(2): 192-197 (1986)] that proposed that
-applications only use queues, stacks, and sets (real sets, with union,
-intersection, and such operations). It's an interesting concept, and I
-agree with the aim of programs using appropriate abstractions and hiding
-lower level implementation details, especially use of pointers.
+   @b<procedure> Delete_Last (Container : @b<in out> List;
+                          Count     : @b<in>     Count_Type := 1);
 
-****************************************************************
+   @b<generic>
+      @b<with function> "<" (Left, Right : Element_Type)
+         @b<return> Boolean is <@>;
+   @b<procedure> Generic_Sort (Container : @b<in out> List);
 
-From: Alexandre E. Kopilovitch
-Sent: Thursday, February 5, 2004  9:04 AM
+   @b<generic>
+      @b<with function> "<" (Left, Right : Element_Type)
+         @b<return> Boolean @b<is> <@>;
+   @b<procedure> Generic_Merge (Target  : @b<in out> List;
+                            Source  : @b<in out> List);
 
-Tucker Taft wrote:
+   @b<procedure> Reverse_List (Container : @b<in out> List);
 
-> 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.
+   @b<procedure> Swap (I, J  : @b<in> Cursor);
 
-So call it Java_Vector - that will be at least consistent.
+   @b<procedure> Swap_Links (Container : @b<in out> List;
+                         I, J      : @b<in>     Cursor);
 
-Do you think that Java meaning for "vector" is more significant for Ada than
-mathematical meaning of this term (which never implied extensibility) ?
+   @b<procedure> Splice (Target   : @b<in out> List;
+                     Before   : @b<in>     Cursor;
+                     Source   : @b<in out> List);
 
-Why not call that thing Flexible_Array (after Algol-68, I think) - this name
-will directly reflect the essense.
+   @b<procedure> Splice (Target   : @b<in out> List;
+                     Before   : @b<in>     Cursor;
+                     Position : @b<in>     Cursor);
 
-****************************************************************
+   @b<procedure> Splice (Target   : @b<in out> List;
+                     Before   : @b<in>     Cursor;
+                     Source   : @b<in out> List;
+                     Position : @b<in>     Cursor);
 
-From: Robert A. Duff
-Sent: Thursday, February 5, 2004  1:37 PM
+   @b<function> First (Container : List) @b<return> Cursor;
 
-Bill Wulf and other professors at CMU circa late 1970's were using the
-term "vector" to mean "array" (not necessarily extensible); that's the
-first time *I* heard it.  So it's not a Java-ism.
+   @b<function> First_Element (Container : List)
+      @b<return> Element_Type;
 
-I think this meaning of "vector" derives from the maths meaning,
-even if it's not precisely the same thing.
+   @b<function> Last (Container : List) @b<return> Cursor;
 
-****************************************************************
+   @b<function> Last_Element (Container : List)
+      @b<return> Element_Type;
 
-From: Stephen Leake
-Sent: Thursday, February 5, 2004  2:18 PM
+   @b<function> Contains (Container : List;
+                      Item      : Element_Type) @b<return> Boolean;
 
-Jeffrey Carter <jrcarter@acm.org> writes:
+   @b<function> Find (Container : List;
+                  Item      : Element_Type;
+                  Position  : Cursor := No_Element)
+      @b<return> Cursor;
 
-> Tucker Taft wrote:
->
-> > 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 disagree, even though I know that's dangerous when discussing Ada
-> with STT. An application that uses both extensible arrays and
-> mathematical vectors will be very confusing if both are called
-> vectors. Since an explicit design goal of Ada is to emphasize ease of
-> reading, calling an extensible array a vector seems inappropriate.
+   @b<function> Reverse_Find (Container : List;
+                          Item      : Element_Type;
+                          Position  : Cursor := No_Element)
+      @b<return> Cursor;
 
-I agree with Tucker. I have code that uses both Cartesian vectors and
-extensible arrays. One is SAL.Math_Double.DOF_3.Cart_Vector_Type, the
-other is SAL.Poly.Unbounded_Arrays. Obviously, I have different names
-for them, as Carter wants. But if I called them
-SAL.Math_Double.DOF_3.Vector and SAL.Poly.Vector, I would have no
-chance of confusion. That's what package hierarchies are for.
+   @b<function> Next (Position : Cursor) @b<return> Cursor;
 
-Since both Java and C++ use the term "vector" for an extensible array,
-I think Ada should also. Part of the point of the OY revision is to
-make the language more attractive to current users of other languages.
-This is an easy way to do that.
+   @b<function> Previous (Position : Cursor) @b<return> Cursor;
 
-> (Replace_Slice and Slice?); and 'First, 'Last, and 'Length (though
-> 'First is a constant for an EA).
+   @b<procedure> Next (Position : @b<in out> Cursor);
 
-'First is not constant for SAL.Poly.Unbounded_Arrays; I provide both
-Append and Prepend operations. I don't think I've ever used Prepend,
-though; it was really just an exercise in what was possible.
+   @b<procedure> Previous (Position : @b<in out> Cursor);
 
-> .. I don't see
-> a need for Front, Back, Insert, Delete, and so on.
+   @b<function> Has_Element (Position : Cursor) @b<return> Boolean;
 
-I use Insert and Delete in real applications.
+   @b<procedure> Iterate
+     (Container : @b<in> List;
+      Process   : @b<not null access procedure> (Position : @b<in> Cursor));
 
-> The proposal says that containers "that are relatively easy to code,
-> redundant, or rarely used are omitted". It also says that lists are
-> difficult to implement correctly. Given a list, structures such as
-> deques, stacks, and especially queues are easy to implement. Since
-> queues are common structures and not redundant (none of the proposed
-> containers provides an efficient implementation of a queue), the
-> proposal itself seems to argue that lists should be provided, since
-> they are not easy to code correctly, and provide a basis for the
-> user to easily code queues.
+   @b<procedure> Reverse_Iterate
+     (Container : @b<in> List;
+      Process   : @b<not null access procedure> (Position : @b<in> Cursor));
 
-I agree. A lists package would be nice.
+@b<private>
 
-But I also agree with Tucker, that it is difficult to come up with one
-list package that really meets a wide range of needs.
+   ... -- @ft<@i<not specified by the language>>
 
-Perhaps one list package, that meets a narrow range of needs, would
-still be useful. It would set a style standard for other list packages.
+@b<end> Ada.Containers.Doubly_Linked_Lists;>
 
-****************************************************************
+The type List is used to represent lists. The type List needs finalization (see
+7.6).
 
-From: Matthew Heaney
-Sent: Thursday, February 5, 2004  2:48 PM
+Empty_List represents the empty List object. It has a length of 0. If an object
+of type List is not otherwise initialized, it is initialized to the same value
+as Empty_List.
 
-Alexandre E. Kopilovitch wrote:
+No_Element represents a cursor that designates no element. If an object of type
+Cursor is not otherwise initialized, it is initialized to the same value as
+No_Element.
 
-> So call it Java_Vector - that will be at least consistent.
->
-> Do you think that Java meaning for "vector" is more significant for Ada than
-> mathematical meaning of this term (which never implied extensibility) ?
->
-> Why not call that thing Flexible_Array (after Algol-68, I think) - this name
-> will directly reflect the essense.
+Some operations are assumed to work on a constant set of elements. For such
+an operation, a subprogram is said to @i<tamper with cursors> of a list object
+@i<L> if:
 
-Tucker T. and Bob D. are both correct: the container is a "vector."
+@xbullet<it inserts or deletes elements of @i<L>, that is, it calls the Insert,
+Clear, Delete, or Delete_Last procedures with @i<L> as a parameter; or>
 
-Alexandre K. and Jeff C. are both incorrect.  The container is not a
-list, not a Java_Vector, not an Extensible_Array, and not a Flexible_Array.
+@xbullet<it reorders the elements of @i<L>, that is, it calls the Splice,
+Swap_Links, or Reverse_List procedures or an instance of Generic_Sort or
+Generic_Merge with C as a parameter; or>
 
-It is a vector.  It has the same semantics as the identically-named
-container in the STL.  The one named "vector."
+@xbullet<it finalizes @i<L>; or>
+@xbullet<it calls the Move procedure with @i<L> as a parameter.>
 
-The container whose name is vector does not have array semantics.  There
-is no slicing for example.
+Some operations are assumed to not change elements. For such an operation, a
+subprogram is said to @i<tamper with elements> of a list object @i<L> if:
 
-The container whose name is vector has the following important properties:
+@xbullet<it tampers with cursors of @i<L>; or>
+@xbullet<it modifies one or more elements of @i<L>, that is, it calls the
+Replace_Element, Update_Element, or Swap procedures with @i<L> as a parameter.>
 
-o inserting at the back end is amortized constant time
-o supports random access of elements, in constant time
+@xcode<@b<function> "=" (Left, Right : List) @b<return> Boolean;>
 
-Yes, internally a vector is implemented as an array.  The Size function
-returns the length of this internal array, and Resize can be used to
-expand its length.
+@xindent<If Left and Right denote the same list object, then the function returns True.
+If Left and Right have different lengths, then the function returns False.
+Otherwise, it compares each element in Left to the corresponding element in
+Right using the generic formal equality operator; if element equality returns
+False, then the function returns False. If the function has not returned a
+result after checking all of the elements, it returns True. Any exception
+raised during evaluation of element equality is propagated.>
+
+@xcode<@b<function> Length (Container : List) @b<return> Count_Type;>
+
+@xindent<Returns the number of elements in Container.>
+
+@xcode<@b<function> Is_Empty (Container : List) @b<return> Boolean;>
+
+@xindent<Equivalent to Length (Container) = 0.>
+
+@xcode<@b<procedure> Clear (Container : @b<in out> List);>
+
+@xindent<Removes all the elements from Container.>
+
+@xcode<@b<function> Element (Position : Cursor) @b<return> Element_Type;>
+
+@xindent<If Position equals No_Element, then Constraint_Error is propagated.
+Otherwise, Element returns the element designated by Position.>
+
+@xcode<@b<procedure> Query_Element
+  (Position : @b<in> Cursor;
+   Process  : @b<not null access procedure> (Element : @b<in> Element_Type));>
+
+@xindent<If Position equals No_Element, then Constraint_Error is propagated.
+Otherwise, Query_Element calls Process.@b<all> with the element on node designated by
+Position as the argument. Program_Error is propagated if Process.@b<all> tampers
+with the elements of Container. Any exception raised by Process.@b<all> is propagated.>
+
+@xcode<@b<procedure> Update_Element
+  (Position : @b<in> Cursor;
+   Process  : @b<not null access procedure> (Element : @b<in out> Element_Type));>
+
+@xindent<If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
+Update_Element calls Process.@b<all> with the element on node designated by
+Position as the argument. Program_Error is propagated if Process.@b<all> tampers
+with the elements of Container. Any exceptions raised by Process.@b<all> are propagated.>
+
+@xindent<If Element_Type is unconstrained and definite, then the Element parameter
+of Process.@b<all> shall be unconstrained.>
+
+@xcode<@b<procedure> Replace_Element (Position : Cursor;
+                           By       : Element_Type);>
+
+@xindent<If Position equals No_Element, then Constraint_Error is propagated. Otherwise
+Replace_Element assigns the value By to the element designated by
+Position.>
+
+@xcode<@b<procedure> Move (Target : @b<in out> List;
+                Source : @b<in out> List);>
+
+@xindent<If Target denotes the same object as Source, then Move has no
+effect. Otherwise, Move first calls Clear (Target). Then, the nodes in Source
+are moved to Target (in the original order). The length of Target is set to the
+length of Source, and the length of Source is set to 0.>
+
+@xcode<@b<procedure> Prepend (Container : @b<in out> List;
+                   New_Item  : @b<in>     Element_Type;
+                   Count     : @b<in>     Count_Type := 1);>
+
+@xindent<Equivalent to Insert (Container, First (Container), New_Item, Count).>
+
+@xcode<@b<procedure> Append (Container : @b<in out> List;
+                  New_Item  : @b<in>     Element_Type;
+                  Count     : @b<in>     Count_Type := 1);>
+
+@xindent<Equivalent to Insert (Container, No_Element, New_Item, Count).>
+
+@xcode<@b<procedure> Insert (Container : @b<in out> List;
+                  Before    : @b<in>     Cursor;
+                  New_Item  : @b<in>     Element_Type;
+                  Count     : @b<in>     Count_Type := 1);>
+
+@xindent<Program_Error is propagated unless Before is equal to No_Element or
+designated an element in Container.
+Otherwise, Insert inserts Count copies of
+New_Item prior to the element designated by Before. If Before equals
+No_Element, the new elements are inserted after the last node (if any). Any
+exception raised during allocation of internal storage is propagated, and
+Container is not modified.>
+
+@xcode<@b<procedure> Insert (Container : @b<in out> List;
+                  Before    : @b<in>     Cursor;
+                  New_Item  : @b<in>     Element_Type;
+                  Position  :    @b<out> Cursor;
+                  Count     : @b<in>     Count_Type := 1);>
+
+@xindent<Program_Error is propagated unless Before is equal to No_Element or
+designated an element in Container.
+Otherwise, Insert allocates Count copies of
+New_Item, and inserts them prior to the element designated by Before. If Before
+equals No_Element, the new elements are inserted after the last element (if
+any). Position designates the first newly-inserted element. Any exception
+raised during allocation of internal storage is propagated, and Container is
+not modified.>
+
+@xcode<@b<procedure> Insert (Container : @b<in out> List;
+                  Before    : @b<in>     Cursor;
+                  Position  :    @b<out> Cursor;
+                  Count     : @b<in>     Count_Type := 1);>
+
+@xindent<Program_Error is propagated unless Before is equal to No_Element or
+designated an element in Container.
+Otherwise, Insert inserts Count new elements
+prior to the element designated by Before. If Before equals No_Element, the new
+elements are inserted after the last node (if any). The new elements are
+initialized with any implicit initial value for any part (as for an
+object_declaration with no initialization expression - see 3.3.1). Any
+exception raised during allocation of internal storage is propagated, and
+Container is not modified.>
+
+@xcode<@b<procedure> Delete (Container : @b<in out> List;
+                  Position  : @b<in out> Cursor;
+                  Count     : @b<in>     Count_Type := 1);>
 
-But it is not an array.  It is a container.  Whose name is "vector".
-Just like the one in the STL.
+@xindent<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 Delete removes (from Container) Count elements starting at the
+element designated by Position (or all of the elements if there are less than
+Count elements starting at Position).>
 
-****************************************************************
+@xcode<@b<procedure> Delete_First (Container : @b<in out> List;
+                        Count     : @b<in>     Count_Type := 1);>
 
-From: Alexandre E. Kopilovitch
-Sent: Thursday, February 5, 2004  3:46 PM
+@xindent<Equivalent to Delete (Container, First (Container), Count).>
 
-No problem with all that if another term was chosen. Now, with "vector", this
-is name squatting (well, participation in name squatting in Ada case), which
-is fully appropriate for Java, somehow understandable for C++, but seems
-(still) inappropriate for Ada, especially taking into account that the involved
-term belongs to some Ada-friendly domain.
+@xcode<@b<procedure> Delete_Last (Container : @b<in out> List;
+                       Count     : @b<in>     Count_Type := 1);>
 
-****************************************************************
+@xindent<If Length (Container) <= Count then Delete_Last is equivalent to Clear
+(Container). Otherwise it removes the last Count nodes from Container.>
 
-From: Robert A. Duff
-Sent: Thursday, February 5, 2004  3:38 PM
+@xcode<@b<generic>
+   @b<with function> "<" (Left, Right : Element_Type) @b<return> Boolean @b<is> <@>;
+@b<procedure> Generic_Sort (Container : @b<in out> List);>
 
-I wrote:
+@xindent<Reorders the nodes of Container such that the elements are
+sorted smallest first as determined by the generic formal "<" operator
+provided. The sort must be stable. Any exception raised during evaluation of
+"<" is propagated.>
 
-> Bill Wulf and other professors at CMU circa late 1970's were using the
-> term "vector" to mean "array" (not necessarily extensible); that's the
-> first time *I* heard it.  So it's not a Java-ism.
+@xcode<@b<generic>
+   @b<with function> "<" (Left, Right : Element_Type) @b<return> Boolean @b<is> <@>;
+@b<procedure> Generic_Merge (Target  : @b<in out> List;
+                         Source  : @b<in out> List);>
 
-Actually, the meaning was "one-dimensional array".  But there was no
-implication that they could grow.
+@xindent<Generic_Merge removes elements from Source and inserts them into Target so that
+Target be sorted smallest first as determined by the generic formal "<"
+operator.>
 
-> I think this meaning of "vector" derives from the maths meaning,
-> even if it's not precisely the same thing.
+@xindent<Any exception raised during evaluation of "<" is propagated. If Target and
+Source are not sorted smallest first, then Program_Error is propagated. In
+these cases, Target is left in an unspecified order, but contains the union of
+the elements that were initially in Source and Target; Source is left empty.>
 
-I mean, what's a vector in 3-space?  Basically, a one-dimensional array
-of 3 real numbers -- the X, Y, and Z coordinates.
+@xcode<@b<procedure> Reverse_List (Container : @b<in out> List);>
 
-Matt wrote:
+@xindent<Reorders the elements of Container in reverse order.>
 
-> It is a vector.  It has the same semantics as the identically-named
-> container in the STL.  The one named "vector."
+@xcode<@b<procedure> Swap (I, J  : @b<in> Cursor);>
 
-This stuff comes from the C++ STL.  I think gratuitous differences from
-that are unhelpful.  (But I admit that I was one of the folks pushing
-for "cursor" instead of "iterator".)
+@xindent<If either I or J is No_Element, then Constraint_Error is propagated. If I and J
+designate elements in different containers, then Program_Error is propagated.
+Otherwise Swap exchanges the values of the elements designated by I and J.>
 
-> The container whose name is vector does not have array semantics.  There
-> is no slicing for example.
+@xcode<@b<procedure> Swap_Links (Container : @b<in out> List;
+                      I, J      : @b<in>     Cursor);>
 
-Well, "no slicing" is hardly fundamental.  It could be added, or
-programmed by the client.
+@xindent<If either I or J is No_Element, then Constraint_Error is propagated. If I or J
+do not designate an element in Container, then Program_Error is propagated.
+Otherwise, Swap_Links exchanges the nodes designated by I and J.>
 
-> The container whose name is vector has the following important properties:
->
-> o inserting at the back end is amortized constant time
-> o supports random access of elements, in constant time
+@xcode<@b<procedure> Splice (Target   : @b<in out> List;
+                  Before   : @b<in>     Cursor;
+                  Source   : @b<in out> List);>
 
-I think "random access" is the essence of array semantics.  After all,
-anything you can do with an array you can do with a linked list, and
-vice versa -- the only fundamental difference is the efficiency
-properties.
+@xindent<Program_Error is propagated unless Before is equal to No_Element or
+designated an element in Target. Otherwise, if Source denotes the
+same object as Target, the
+operation has no effect. Otherwise, Splice reorders elements such that they are
+removed from Source and moved to Target, immediately prior to Before. If Before
+equals No_Element, the nodes of Source are spliced after the last node of
+Target. The length of Target is incremented by the number of nodes in Source,
+and the length of Source is set to 0.>
 
-****************************************************************
+@xcode<@b<procedure> Splice (Target   : @b<in out> List;
+                  Before   : @b<in>     Cursor;
+                  Position : @b<in>     Cursor);>
 
-From: Matthew Heaney
-Sent: Thursday, February 5, 2004  9:31 AM
+@xindent<If either of Before or Position is not No_Element, and does not designate an
+element in Target, then Program_Error is propagated. If Position equals
+No_Element, or if Position equals Before, or if the successor of Position
+equals Before, the operation has no effect. Otherwise the element designated by
+Position is moved immediately prior to Before, or, if Before equals No_Element,
+after the last element.>
 
-Robert A Duff wrote:
+@xcode<@b<procedure> Splice (Target   : @b<in out> List;
+                  Before   : @b<in>     Cursor;
+                  Source   : @b<in out> List;
+                  Position : @b<in>     Cursor);>
 
-> This stuff comes from the C++ STL.  I think gratuitous differences from
-> that are unhelpful.  (But I admit that I was one of the folks pushing
-> for "cursor" instead of "iterator".)
+@xindent<If Position is No_Element then Constraint_Error is propagated. If Before does
+not equal No_Element, and does not designate an element in Target, then
+Program_Error is propagated. If Position does not equal No_Element, and does
+not designate a node in Source, then Program_Error is propagated. If Source
+denotes the same object as Target, then Splice is equivalent to Splice (Target,
+Before, Position). Otherwise the element designated by Position is removed from
+Source and moved to Target, immediately prior to Before, or, if Before equals
+No_Element, after the last element of Target. The length of Target is
+incremented, and the length of Source is decremented.>
 
-Yes.  The world has settled on the name "vector."  Let's use the terms
-everyone else is using, unless we have a good reason not to.
+@xcode<@b<function> First (Container : List) @b<return> Cursor;>
 
-(BTW, that's also why I used the name "Iterator_Type".  But I have no
-issues with the name "Cursor_Type".)
+@xindent<If Container is empty, First returns the value No_Element. Otherwise it returns
+a cursor that designates the first node in Container.>
 
+@xcode<@b<function> First_Element (Container : List) @b<return> Element_Type;>
 
-> I think "random access" is the essence of array semantics.  After all,
-> anything you can do with an array you can do with a linked list, and
-> vice versa -- the only fundamental difference is the efficiency
-> properties.
+@xindent<Equivalent to Element (First (Container)).>
 
-But that's the essence of the argument!
+@xcode<@b<function> Last (Container : List) @b<return> Cursor;>
 
-Yes, it's *possible* to seek to specific elements in a linked list, but
-I would hardly call that "random access."
+@xindent<If Container is empty, Last returns the value No_Element. Otherwise it returns a
+cursor that designates the last node in Container.>
 
-If you need fast random access to the elements in a container, and the
-number of elements in the container is large, then you can effectively
-rule out using a linked list as the container.
+@xcode<@b<function> Last_Element (Container : List) @b<return> Element_Type;>
 
-Of course you could make the argument the other way.  If you need
-constant-time insertion of elements at any position, then that
-effectively rules out a vector, in favor of a list.
+@xindent<Equivalent to Element (Last (Container)).>
 
-****************************************************************
+@xcode<@b<function> Contains (Container : List;
+                   Item      : Element_Type) @b<return> Boolean;>
 
-From: Alexandre E. Kopilovitch
-Sent: Thursday, February 5, 2004  3:21 PM
+@xindent<Equivalent to Find (Container, Item) /= No_Element.>
 
-Robert A Duff wrote:
+@xcode<@b<function> Find (Container : List;
+               Item      : Element_Type;
+               Position  : Cursor := No_Element)
+  @b<return> Cursor;>
 
-> Bill Wulf and other professors at CMU circa late 1970's were using the
-> term "vector" to mean "array" (not necessarily extensible); that's the
-> first time *I* heard it.
+@xindent<If Position is not No_Element, and does not designate an element
+in Container, then Program_Error is propagated. Find searches the elements of
+Container for an element equal to Item (in the sense of the generic formal
+equality operator). The search starts at the element designated by Position, or
+at the first element if Position equals No_Element. It proceeds towards Last
+(Container). If no equal element is found, then Find returns No_Element.
+Otherwise, it returns a cursor designating the first equal element encountered.>
 
-Yes, CMU always was (as far as I know) primarily engineering educational
-facility, and I know well that engineers (not software engineers, but rather
-general kind of engineers) often called "vector" any column or row of numbers.
-(not bothering themselves with the question how the components of that "vector"
-transform with a change of coordinate system). But apparently they never used
-this term for arrays of any other objects, and I almost never seen a case
-(even in engineering) where "vector" was used for extensible array - except
-Java and perhaps some C++ libraries.
+@xcode<@b<function> Reverse_Find (Container : List;
+                       Item      : Element_Type;
+                       Position  : Cursor := No_Element)
+   @b<return> Cursor;>
 
-A notable exception is APL, in which "vector" is the basic term, and that
-"vector" is extensible. But in APL that "vector" is equipped with vast
-nomenclature of functions, many of them associated with genuine mathematical
-vectors, so the entire balance for the term was acceptable.
+@xindent<If Position is not No_Element, and does not designate an element
+in Container, then Program_Error is propagated. Find searches the elements of
+Container for an element equal to Item (in the sense of the generic formal
+equality operator). The search starts at the element designated by Position, or
+at the lastelement if Position equals No_Element. It proceeds towards First
+(Container). If no equal element is found, then Reverse_Find returns
+No_Element. Otherwise, it returns a cursor designating the first equal element
+encountered.>
 
-> So it's not a Java-ism.
+@xcode<@b<function> Next (Position : Cursor) @b<return> Cursor;>
 
-Yes, not exactly - there were other precedents of sloppy usage of this term.
-But nevertheless a strong impression remains that it is exactly Java, which
-is a real reason, ground and reference for proposing this term for extensible
-arrays *now and for Ada0Y*.
+@xindent<If Position equals No_Element or designates the last element of the container,
+then Next returns the value No_Element. Otherwise, it returns a cursor that
+designates the successor of the element designated by Position.>
 
-> I think this meaning of "vector" derives from the maths meaning,
-> even if it's not precisely the same thing.
+@xcode<@b<function> Previous (Position : Cursor) @b<return> Cursor;>
 
-No, not at all - it lacks the primary mathematical meaning of it, and adds
-the primary feature, which meaning is totally non-mathematical (that is, there
-is no attempt to bring any mathematical meaning to it... and it will not be
-simple, if attempted).
+@xindent<If Position equals No_Element or designates the first element of the container,
+then Previous returns the value No_Element. Otherwise, it returns a cursor that
+designates the predecessor of the element designated by Position.>
 
-****************************************************************
+@xcode<@b<procedure> Next (Position : @b<in out> Cursor);>
 
-From: Matthew Heaney
-Sent: Thursday, February 5, 2004  5:11 PM
+@xindent<Equivalent to Position := Next (Position).>
 
+@xcode<@b<procedure> Previous (Position : @b<in out> Cursor);>
 
+@xindent<Equivalent to Position := Previous (Position).>
 
-Jeffrey Carter wrote:
+@xcode<@b<function> Has_Element (Position : Cursor) @b<return> Boolean;>
 
-> 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.
+@xindent<Returns True if Position designates an element, and returns False otherwise.>
 
-In Charles I copied the hash function from GNAT.  I figure if it's good
-enough for Robert Dewar it's good enough for me...
+@xcode<@b<procedure> Iterate
+  (Container : @b<in> List;
+   Process   : @b<not null access procedure> (Position : @b<in> Cursor));>
 
+@xindent<Iterate calls Process.@b<all> with a cursor that designates each node in Container,
+starting with the first node and moving the cursor as per the Next function.
+Program_Error is propagated if Process.@b<all> tampers with the cursors of
+Container. Any exception raised by Process.@b<all> is propagated.>
 
+@xcode<@b<procedure> Reverse_Iterate
+  (Container : @b<in> List;
+   Process   : @b<not null access procedure> (Position : @b<in> Cursor));>
 
-> Vector should have an iterator, in addition to allowing the user to
-> explicitly iterate over the structure.
+@xindent<Iterates over the nodes in Container as per Iterate, except that elements are
+traversed in reverse order, starting with the last node and moving the cursor
+as per the Previous function.>
 
-No.  Vector iterators are fragile, and hence very error prone.
+@i<@s8<Erroneous Execution>>
 
-They are fragile because the (logical) internal array gets thrown away
-during expansion, which invalidates the iterator.  It's too hard to keep
-track of whether a vector iterator is still valid, and most of the time
-you end up with a dangling reference.
+A Cursor value is @i<invalid> if any of the following have occurred since it was
+created:
+@xbullet<The list that contains the element it designates has been finalized;>
+@xbullet<The list that contains the element it designates has been used as the
+    Source or Target of a call to Move;>
+@xbullet<The element it designates has been deleted.>
 
-The STL has vector iterators in order to provide the infrastructure
-necessary to support generic algorithms.
+The result of "=" or Has_Element is unspecified if it is called with an invalid
+cursor parameter. Execution is erroneous if any other subprogram declared in
+Containers.Doubly_Linked_Lists is called with an invalid cursor parameter.
 
-In Ada they are not necessary, because you can use locally-declared
-subprograms to fit within such a framework.
+@i<@s8<Implementation Requirements>>
 
+No storage associated with a doubly-linked List object shall be lost
+upon assignment or scope exit.
 
+@i<@s8<Implementation Advice>>
 
+Containers.Doubly_Linked_Lists should be implemented similarly to a linked
+list. In particular, if @i<N> is the length of a list, then the worst-case time
+complexity of Element, Insert with Count=1, and Delete with Count=1 should be
+O(log @i<N>).
 
->> 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.
+The worst-case time complexity of a call on an instantiation of
+Containers.Doubly_Linked_Lists.Generic_Sort should be O(@i<N>**2), and
+the average time complexity should be better than O(@i<N>**2).
 
-Front can probably go away.  First is there for consistency with other
-containers.
+Move should not copy elements, and should minimize copying of internal
+data structures.
 
+@xindent<@s9<NOTES:@hr
+43 Sorting a list never copies elements, and is a stable sort (equal elements
+remain in the original order). This is different than sorting an array or
+vector, which may need to copy elements, and is probably not a stable sort.>>
 
+!corrigendum A.18.4
 
-> 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.
+@dinsc
+The language-defined generic packages Containers.Hashed_Maps and
+Containers.Ordered_Maps provide private types Map and Cursor, and a set of
+operations for each type. A map container allows an arbitrary type to be used
+as a key to find the element associated with that key. A hashed map uses a hash
+function to organize the keys, while an ordered map orders the keys per a
+specified relation.
 
-That's not really possible for generic actual index types such as
-Natural or Positive.
+This section describes the declarations that are common to both kinds of maps.
+See A.18.5 for a description of the semantics specific to Containers.Hashed_Maps
+and A.18.6 for a description of the semantics specific to
+Containers.Ordered_Maps.
 
-We could get rid of the assertion, but this would impact implementors.
-That's why it's still an open issue.
+@i<@s8<Static Semantics>>
 
-In my reference implementation, I don't think the generic actual type
-has to have IT'Base'First < IT'First, since internally I use Integer
-subtypes for everything.
+The type Map is used to represent maps. The type Map needs finalization (see
+7.6).
 
-http://home.earthlink.net/~matthewjheaney/charles/ai302-20040205.zip
+A map contains pairs of keys and elements, called @i<nodes>. Map cursors
+designate nodes, but also can be thought of as designating an element (the
+element contained in the node) for consistency with the other containers. There
+exists an equivalence relation on keys, whose definition is different for hashed
+maps and ordered maps. A map never contains two or more nodes with equivalent
+keys. The @i<length> of a map is the number of nodes it contains.
 
+Each nonempty map has two particular nodes called the @i<first node> and the
+@i<last node> (which may be the same). Each node except for the last node has a
+@i<successor node>. If there are no other intervening operations, starting with
+the first node and repeatedly going to the successor node will visit each node
+in the map exactly once until the last node is reached. The exact definition of
+these terms is different for hashed maps and ordered maps.
 
+Some operations are assumed to work on a constant set of elements. For such
+an operation, a subprogram is said to @i<tamper with cursors> of a map object @i<M>
+if:
 
-> All the problems with Index_Type disappear with a general list, which
-> would use a cursor.
+@xbullet<it inserts or deletes elements of @i<M>, that is, it calls the Insert,
+Include, Clear, Delete, or Exclude procedures with @i<M> as a parameter; or>
 
-The original proposal included list containers, but they were not
-included in the subcommittee report, in order to keep the size of the
-report more manageable.
+@xbullet<it finalizes @i<M>; or>
 
+@xbullet<it calls the Move procedure with @i<M> as a parameter; or>
 
+@xbullet<it calls one of the operations defined to tamper with the cursors of @i<M>.>
 
-> 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.
+Some operations are assumed to not change elements. For such an operation, a
+subprogram is said to @i<tamper with elements> of a map object @i<M> if:
 
-My original proposal had both sorted and hashed maps, but in order to
-keep the subcommittee report small support for sorted maps was removed.
+@xbullet<it tampers with cursors of @i<M>; or>
 
+@xbullet<it modifies one or more elements of @i<M>, that is, it calls the
+Replace, Replace_Element, or Update_Element procedures with @i<M> as a
+parameter.>
 
-> 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.
+Empty_Map represents the empty Map object. It has a length of 0. If an object
+of type Map is not otherwise initialized, it is initialized to the same
+value as Empty_Map.
 
-That's what the sorted set is for.
+No_Element represents a cursor that designates no node. If an object of type
+Cursor is not otherwise initialized, it is initialized to the same
+value as No_Element.
 
+@xcode<@b<function> "=" (Left, Right : Map) @b<return> Boolean;>
 
-> None of these applications use key/value pairs.
+@xindent<If Left and Right denote the same map object, then the function returns True. If
+Left and Right have different lengths, then the function returns False.
+Otherwise, for each key @i<K> in Left, the function returns False if:>
 
-So use the sorted set.
+@xinbull<a key equivalent to @i<K> is not present in Right; or>
 
+@xinbull<the element associated with @i<K> in Left is not equal to the element
+associated with @i<K> in Right (using the generic formal equality operator for
+elements).>
 
-> Therefore, I think it's
-> important to provide the underlying searchable structure to users.
+@xindent<If the function has not returned a result after checking all of the keys, it
+returns True. Any exception raised during evaluation of key equivalence or
+element equality is propagated.>
 
-Just use the sorted set container.  If guarantees that searches only
-take O (log N) even in the worst case.
+@xcode<@b<function> Length (Container : Map) @b<return> Count_Type;>
 
+@xindent<Returns the number of nodes in Container.>
 
-> (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.)
+@xcode<@b<function> Is_Empty (Container : Map) @b<return> Boolean;>
 
-The (hashed) map stores the key and element as separate components of
-the internal node of storage.
+@xindent<Equivalent to Length (Container) = 0.>
 
-If you have a record like that, containing a key-part component, then
-use the sorted set, and instantiate the nested generic package Generic_Keys.
+@xcode<@b<procedure> Clear (Container : @b<in out> Map);>
 
+@xindent<Removes all the nodes from Container.>
 
-> 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?
+@xcode<@b<function> Key (Position : Cursor) @b<return> Key_Type;>
 
-Yes, we really need string-key maps.
+@xindent<If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
+Key returns the key component of the node designated by Position.>
 
+@xcode<@b<function> Element (Position : Cursor) @b<return> Element_Type;>
 
-> 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.
+@xindent<If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
+Element returns the element component of the node designated by Position.>
 
-A "set" is really any sorted sequence of items.  If you want set
-intersection, symmetric difference, etc, then just use a generic
-algorithm.  See the Charles library for such algorithms.
+@xcode<@b<procedure> Query_Element
+  (Position : @b<in> Cursor;
+   Process  : @b<not null access procedure> (Key     : @b<in> Key_Type;
+                                         Element : @b<in> Element_Type));>
 
-Of course, if you want target of a set union operation to be the set
-itself, then just use Insert to insert the items.
+@xindent<If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
+Query_Element calls Process.@b<all> with the key and element from the node
+designated by Position as the arguments. Program_Error is propagated if
+Process.@b<all> tampers with the elements of Container. Any exceptions raised by
+Process.@b<all> are propagated.>
 
-The subcommittee report has several examples of how sets are used, and
-there's at least one example showing how to use the nested generic package.
+@xcode<@b<procedure> Update_Element
+  (Position : @b<in> Cursor;
+   Process  : @b<not null access procedure> (Key     : @b<in> Key_Type;
+                                         Element : @b<in out> Element_Type));>
 
-See the last two slides in my AE-2003 paper presentation for an example
-of how to take the union of a set and a (sorted) list:
+@xindent<If Position equals No_Element, then Constraint_Error is propagated. Otherwise,
+Update_Element calls Process.@b<all> with the key and element from the node
+designated by Position as the arguments. Program_Error is propagated if
+Process.@b<all> tampers with the elements of Container. Any exceptions raised
+by Process.@b<all> are propagated.>
 
-http://home.earthlink.net/~matthewjheaney/charles/charlesppt.htm
+@xindent<If Element_Type is unconstrained and definite, then the Element parameter
+of Process.@b<all> shall be unconstrained.>
 
-My original proposal has the same example at the very end:
+@xcode<@b<procedure> Replace_Element (Position : @b<in> Cursor;
+                           By       : @b<in> Element_Type);>
 
-http://home.earthlink.net/~matthewjheaney/charles/ai302.txt
+@xindent<If Position equals No_Element, then Constraint_Error is propagated.
+Otherwise Replace_Element assigns By to the element of the node designated by
+Position.>
 
+@xcode<@b<procedure> Move (Target : @b<in out> Map;
+                Source : @b<in out> Map);>
 
+@xindent<If Target denotes the same object as Source, then Move has no effect.
+Otherwise, Move first calls Clear (Target). Then, each node from Source is
+removed from Source and inserted into Target. The length of Source is 0 after a
+successful call to Move.>
 
-> "Sans" is a French word. Since the ARM is in English, we should use the
-> English "without" instead. "No" might also be acceptable.
+@xcode<@b<procedure> Insert (Container : @b<in out> Map;
+                  Key       : @b<in>     Key_Type;
+                  New_Item  : @b<in>     Element_Type;
+                  Position  :    @b<out> Cursor;
+                  Inserted  :    @b<out> Boolean);>
 
-Je crois que non.  C'est une bonne idea.
+@xindent<Insert checks if a node with a key equivalent to Key is already present in
+Container. If a match is found, Inserted is set to False and Position
+designates the element with the matching key. Otherwise, Insert allocates a new
+node, initializes it to Key and New_Item, and adds it to Container; Inserted is
+set to True and Position designates the newly-inserted node. Any exception
+raised during allocation is propagated and Container is not modified.>
 
-The name for Delete_Sans_Increment comes from Emacs lisp, which has the
-functions file-name-sans-extension and file-name-sans-versions.
+@xcode<@b<procedure> Insert (Container : @b<in out> Map;
+                  Key       : @b<in>     Key_Type;
+                  Position  :    @b<out> Cursor;
+                  Inserted  :    @b<out> Boolean);>
 
-It was also in homage to Ada's French history, given that her original
-designer was French, and worked for a French company.
+@xindent<Insert inserts Key into Container as per the five-parameter Insert, with the
+difference that an element initialized with any implicit initial values for any
+part (as for an object_declaration with no initialization expression - see
+3.3.1) is inserted.>
 
-Why do you think "rendevous" was named that way?
+@xcode<@b<procedure> Insert (Container : @b<in out> Map;
+                  Key       : @b<in>     Key_Type;
+                  New_Item  : @b<in>     Element_Type);>
 
+@xindent<Insert inserts Key and New_Item into Container as per the five-parameter
+Insert, with the difference that if a node with a key equivalent to Key is
+already in the map, then Constraint_Error is propagated.>
 
+@xcode<@b<procedure> Include (Container : @b<in out> Map;
+                   Key       : @b<in>     Key_Type;
+                   New_Item  : @b<in>     Element_Type);>
 
-> 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.
+@xindent<Include inserts Key and New_Item into Container as per the five-parameter
+Insert, with the difference that if a node with a key equivalent to Key is
+already in the map, then this operation assigns Key and New_Item to the
+matching node. Any exception raised during assignment is propagated.>
 
-If you don't immediately grok how vectors and sets and maps work, then I
-suggest familiarizing yourself with the STL. There are lots of tutorials
-on the WWW.
+@xcode<@b<procedure> Replace (Container : @b<in out> Map;
+                   Key       : @b<in>     Key_Type;
+                   New_Item  : @b<in>     Element_Type);>
 
-I also recommend Stanley Lippman's little book Essential C++.  That was
-my introduction to the STL, and what originally convinced me that
-Stepanov's approach was the correct one.
+@xindent<Replace checks if a node with a key equivalent to Key is present in Container.
+If a match is found, Replace assigns Key and New_Item to the matching node;
+otherwise, Constraint_Error is propagated.>
 
-You might also like Accelerated C++ by Andrew Koenig and Barbara Moo,
-which uses the STL as a basis for teaching C++.
+@xcode<@b<procedure> Delete (Container : @b<in out> Map;
+                  Key       : @b<in>     Key_Type);>
 
-****************************************************************
+@xindent<Delete checks if a node with a key equivalent to Key is present in Container.
+If a match is found, Delete removes the node from the map; otherwise,
+Constraint_Error is propagated.>
 
-From: Randy Brukardt
-Sent: Thursday, February 5, 2004  5:49 PM
+@xcode<@b<procedure> Delete (Container : @b<in out> Map;
+                  Position  : @b<in out> Cursor);>
 
-Matt's too modest. The tutorial that makes up the !example section is
-actually quite good. I learned a lot about how the packages work (and how to
-use them) from reading it carefully, and I recommend that everyone do that
-to better understand Matt's work.
+@xindent<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, Delete removes the node designated by Position from the map.
+Position is set to No_Element on return.>
 
-****************************************************************
+@xcode<@b<procedure> Exclude (Container : @b<in out> Map;
+                   Key       : @b<in>     Key_Type);>
 
-From: Randy Brukardt
-Sent: Thursday, February 5, 2004  3:48 PM
+@xindent<Exclude checks if a node with a key equivalent to Key is present in Container.
+If a match is found, Exclude removes the node from the map and then
+deallocates the node.>
 
-Jeffrey Carter wrote:
+@xcode<@b<function> Contains (Container : Map;
+                   Key       : Key_Type) @b<return> Boolean;>
 
-...
-> > 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).
->
-> I have no objections to an extensible array, provided it's clearly
-> identified as such. I think it should look different from the proposal,
-> but that's mainly a taste issue. I'd want direct analogs to indexing,
-> both LHS and RHS (Put and Get?); slices, both LHS and RHS (Replace_Slice
-> and Slice?); and 'First, 'Last, and 'Length (though 'First is a constant
-> for an EA). An equivalent to 'range would be nice, but impossible. The
-> only difference to a normal array would be that Put and Replace_Slice
-> can accept indices not in First .. Last. I haven't given it a great deal
-> of thought, so I'm sure I'm missing some subtleties, but I don't see a
-> need for Front, Back, Insert, Delete, and so on.
-
-Let's see:
-- direct analogs to indexing, both LHS and RHS (Element, Replace_Element);
-- slices (nope);
-- 'First (First), 'Last (Last), 'Length (Length);
-
-Looks like pretty much everything is in there. And slicing will be expensive
-if the implementation is not a straight array, so it's somewhat dubious.
-Insert and Delete provide easier ways of adding or removing items than
-slices - and how often do you use a slice of a non-string type for something
-other than inserting or deleting elements anyway??
-
-Ada doesn't (and isn't) going to support user-defined indexing or
-user-defined attributes, so this is about the best you can do. So what's the
-complaint (other than the name)??
+@xindent<Equivalent to Find (Container, Key) /= No_Element.>
 
-> The proposal says that containers "that are relatively easy to code,
-> redundant, or rarely used are omitted". It also says that lists are
-> difficult to implement correctly.
+@xcode<@b<function> Find (Container : Map;
+               Key       : Key_Type) @b<return> Cursor;>
 
-I think that's a mistake; only very rare operations are difficult to code.
-We didn't update every piece of the original text, and that one is
-misleading.
+@xindent<If Length (Container) equals 0, then Find returns No_Element. Otherwise, Find
+checks if a node with a key equivalent to Key is present in Container. If a
+match is found, a cursor designating the matching node is returned; otherwise,
+No_Element is returned.>
 
-> Given a list, structures such as
-> deques, stacks, and especially queues are easy to implement. Since
-> queues are common structures and not redundant (none of the proposed
-> containers provides an efficient implementation of a queue), the
-> proposal itself seems to argue that lists should be provided, since they
-> are not easy to code correctly, and provide a basis for the user to
-> easily code queues.
-
-The user can easily code a queue in terms of a Vector (that's one of the
-uses of Insert!). We dropped the list component because it had an identical
-interface to the Vector component, but was less flexible (no computed O(1)
-access).
-
-In any case efficiency is not a goal of the standard containers. It would be
-incorrect for the standard to specify performance to the point that only a
-single implementation would be possible. Moreover, we anticipate a secondary
-standard that *does* try to provide more control over performance (by adding
-lists, bounded forms, etc.)
-
-In my view, it is a mistake for projects to depend on standard containers
-where there are critical performance requirements (not just time, but also
-space as well). In that case, you really have to have control of the
-implementation -- you really need *all* of the source code. You can't trust
-something provided by the standard (or your compiler vendor) in those cases.
-
-In any case, the purpose of these containers is to provide a seed and a
-standard direction. I would hope that they would reduce the tower of babel
-that Ada containers are nowdays - by providing a style for other containers
-to follow. No one is suggesting that these are sufficient to solve all
-programming problems - just 80% of them, especially in prototypes and in Q&D
-programs.
+@xcode<@b<function> Element (Container : Map;
+                  Key       : Key_Type) @b<return> Element_Type;>
 
-****************************************************************
+@xindent<Equivalent to Element (Find (Container, Key)).>
 
-From: Martin Dowie
-Sent: Thursday, February 5, 2004  5:50 PM
+@xcode<@b<function> First (Container : Map) @b<return> Cursor;>
 
-> 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.
+@xindent<If Length (Container) = 0, then First returns No_Element. Otherwise,
+First returns a cursor that designates the first node in Container.>
 
-I was thinking, primarily, of a project that used single (bounded) lists to
-hold commands (a basic, domain-specific, scripting language I guess),
-one of which was 'stop this sequence of commands'.
-
-This pattern has since shown itself to be quite common in embedded
-systems - for either domain-specific scripting languages or graphics.
-
-There is the other idiom where one is processing an iteration of items
-and an external event occurs that stops the processing - e.g. the 'stop'
-button is pushed on a GUI-search window, but it could equally be a
-50Hz message over a 1553.
+@xcode<@b<function> Next (Position  : Cursor) @b<return> Cursor;>
 
-****************************************************************
+@xindent<Returns a cursor that designates the successor of the node designated by
+Position. If Position designates the last node, then No_Element is returned. If
+Position equals No_Element, then No_Element is returned.>
 
-From: Randy Brukardt
-Sent: Thursday, February 5, 2004  6:14 PM
+@xcode<@b<procedure> Next (Position  : @b<in out> Cursor);>
 
-> I was thinking, primarily, of a project that used single (bounded) lists to
-> hold commands (a basic, domain-specific, scripting language I guess),
-> one of which was 'stop this sequence of commands'.
-
-My understanding of the model is that passive iterators are only for cases
-where you want to iterate over the entire container. Thus, this is clearly a
-use for an active iterator. Indeed, given the iteration model of packages,
-there's hardly any reason to use a passive iterator. They're harder to write
-(a subprogram and instantiation are required), and (especially if a Quit
-parameter is provided), harder to understand.
-
-We dropped the passive iterator from the Ada.Directories package precisely
-because even ARG members were confused about how it worked. Even though it
-was a classic passive iterator with a Quit parameter. Perhaps the confusion
-really was the Quit parameter (I thought it was the whole idea), but in any
-case, you've got to keep them simple.
+@xindent<Equivalent to Position := Next (Position).>
 
-> This pattern has since shown itself to be quite common in embedded
-> systems - for either domain-specific scripting languages or graphics.
->
-> There is the other idiom where one is processing an iteration of items
-> and an external event occurs that stops the processing - e.g. the 'stop'
-> button is pushed on a GUI-search window, but it could equally be a
-> 50Hz message over a 1553.
-
-It seems to me that an abort situation is best handled by propagating an
-exception. Otherwise, you end up distributing termination code/flags
-everywhere in the application. But YMMV.
+@xcode<@b<function> Has_Element (Position : Cursor) @b<return> Boolean;>
 
-****************************************************************
+@xindent<Returns True if Position designates a node, and returns False otherwise.>
 
-From: Jeffery Carter
-Sent: Thursday, February 5, 2004  6:39 PM
+@xcode<@b<procedure> Iterate
+  (Container : @b<in> Map;
+   Process   : @b<not null access procedure> (Position : @b<in> Cursor));>
 
-Matthew Heaney wrote:
+@xindent<Iterate calls Process.@b<all> with a cursor that designates each node
+in Container, starting with the first node and moving the cursor according to
+the successor relation. Program_Error is propagated if Process.@b<all> tampers
+with the elements of Container. Any exception raised by Process.@b<all> is
+propagated.>
 
-> Alexandre K. and Jeff C. are both incorrect.  The container is not a
->  list, not a Java_Vector, not an Extensible_Array, and not a
-> Flexible_Array.
+@i<@s8<Erroneous Execution>>
 
-Matthew H. is incorrect. The data structure is not a vector.
+A Cursor value is @i<invalid> if any of the following have occurred since it was
+created:
+@xbullet<The map that contains the node it designates has been finalized;>
+@xbullet<The map that contains the node it designates has been used as the
+Source or Target of a call to Move;>
+@xbullet<The node it designates has been deleted from the map.>
 
-I am at least as qualified as Matthew H. to make such pronouncements.
+The result of "=" or Has_Element is unspecified if these functions are called
+with an invalid cursor parameter. Execution is erroneous if any other subprogram
+declared in Containers.Hashed_Maps or Containers.Ordered_Maps is called with an
+invalid cursor parameter.
 
-****************************************************************
+@i<@s8<Implementation Requirements>>
 
-From: Jeffery Carter
-Sent: Friday, February 6, 2004  1:05 PM
+No storage associated with a Map object shall be lost upon assignment or
+scope exit.
+
+@i<@s8<Implementation Advice>>
+
+Move should not copy elements, and should minimize copying of internal
+data structures.
+
+!corrigendum A.18.5
+
+@dinsc
+
+@i<@s8<Static Semantics>>
+
+The generic library package Containers.Hashed_Maps has the following
+declaration:
+
+@xcode<@b<generic>
+   @b<type> Key_Type @b<is private>;
+   @b<type> Element_Type @b<is private>;
+   @b<with function> Hash (Key : Key_Type) @b<return> Hash_Type;
+   @b<with function> Equivalent_Keys (Left, Right : Key_Type)
+      @b<return> Boolean;
+   @b<with function> "=" (Left, Right : Element_Type)
+      @b<return> Boolean is <@>;
+@b<package> Ada.Containers.Hashed_Maps @b<is>
+   @b<pragma> Preelaborate (Hashed_Maps);
+
+   @b<type> Map @b<is tagged private>;
+
+   @b<type> Cursor @b<is private>;
+
+   Empty_Map : @b<constant> Map;
+
+   No_Element : @b<constant> Cursor;
+
+   @b<function> "=" (Left, Right : Map) @b<return> Boolean;
+
+   @b<function> Length (Container : Map) @b<return> Count_Type;
+
+   @b<function> Is_Empty (Container : Map) @b<return> Boolean;
+
+   @b<procedure> Clear (Container : @b<in out> Map);
+
+   @b<function> Key (Position : Cursor) @b<return> Key_Type;
+
+   @b<function> Element (Position : Cursor) @b<return> Element_Type;
+
+   @b<procedure> Query_Element
+     (Position : @b<in> Cursor;
+      Process  : @b<not null access procedure> (Key     : @b<in> Key_Type;
+                                            Element : @b<in> Element_Type));
+
+   @b<procedure> Update_Element
+     (Position : @b<in> Cursor;
+      Process  : @b<not null access procedure> (Key     : @b<in> Key_Type;
+                                            Element : @b<in out> Element_Type));
+
+   @b<procedure> Replace_Element (Position : @b<in> Cursor;
+                              By       : @b<in> Element_Type);
+
+   @b<procedure> Move (Target : @b<in out> Map;
+                   Source : @b<in out> Map);
+
+   @b<procedure> Insert (Container : @b<in out> Map;
+                     Key       : @b<in>     Key_Type;
+                     New_Item  : @b<in>     Element_Type;
+                     Position  :    @b<out> Cursor;
+                     Inserted  :    @b<out> Boolean);
+
+   @b<procedure> Insert (Container : @b<in out> Map;
+                     Key       : @b<in>     Key_Type;
+                     Position  :    @b<out> Cursor;
+                     Inserted  :    @b<out> Boolean);
+
+   @b<procedure> Insert (Container : @b<in out> Map;
+                     Key       : @b<in>     Key_Type;
+                     New_Item  : @b<in>     Element_Type);
+
+   @b<procedure> Include (Container : @b<in out> Map;
+                      Key       : @b<in>     Key_Type;
+                      New_Item  : @b<in>     Element_Type);
+
+   @b<procedure> Replace (Container : @b<in out> Map;
+                      Key       : @b<in>     Key_Type;
+                      New_Item  : @b<in>     Element_Type);
+
+   @b<procedure> Delete (Container : @b<in out> Map;
+                     Key       : @b<in>     Key_Type);
+
+   @b<procedure> Delete (Container : @b<in out> Map;
+                     Position  : @b<in out> Cursor);
+
+   @b<procedure> Exclude (Container : @b<in out> Map;
+                      Key       : @b<in>     Key_Type);
+
+   @b<function> Contains (Container : Map;
+                      Key       : Key_Type) @b<return> Boolean;
+
+   @b<function> Find (Container : Map;
+                  Key       : Key_Type)
+      @b<return> Cursor;
+
+   @b<function> Element (Container : Map;
+                     Key       : Key_Type)
+      @b<return> Element_Type;
+
+   @b<function> First (Container : Map)
+      @b<return> Cursor;
+
+   @b<function> Next (Position  : Cursor) @b<return> Cursor;
+
+   @b<procedure> Next (Position  : @b<in out> Cursor);
+
+   @b<function> Has_Element (Position : Cursor) @b<return> Boolean;
+
+   @b<function> Equivalent_Keys (Left, Right : Cursor)
+      @b<return> Boolean;
+
+   @b<function> Equivalent_Keys (Left  : Cursor;
+                             Right : Key_Type)
+      @b<return> Boolean;
+
+   @b<function> Equivalent_Keys (Left  : Key_Type;
+                             Right : Cursor)
+      @b<return> Boolean;
+
+   @b<procedure> Iterate
+     (Container : @b<in> Map;
+      Process   : @b<not null access procedure> (Position : @b<in> Cursor));
+
+   @b<function> Capacity (Container : Map) @b<return> Count_Type;
+
+   @b<procedure> Reserve_Capacity (Container : @b<in out> Map;
+                               Capacity  : @b<in>     Count_Type);
+
+@b<private>
+
+   ... -- @ft<@i<not specified by the language>>
+
+@b<end> Ada.Containers.Hashed_Maps;>
+
+An object of type Map contains an expandable hash table, which is used to
+provide direct access to nodes. The @i<capacity> of an object of type Map is
+the maximum number of nodes that can be inserted into the hash table prior to it
+being automatically expanded.
+
+Two keys @i<K1> and @i<K2> are defined to be @i<equivalent> if
+Equivalent_Keys (@i<K1>, @i<K2>) returns True.
+
+Function Hash is expected to return the same value each time it is called with a
+particular key value. For any two equivalent key values, Hash is expected to
+return the same value. If Hash behaves in some other manner, the behavior of
+this package is unspecified. Which subprograms of this package call Hash, and
+how many times they call it, is unspecified.
+
+Function Equivalent_Keys is expected to return the same value each time it is
+called with a particular pair of key values. For any two keys @i<K1> and @i<K2>, the
+boolean values Equivalent_Keys (@i<K1>, @i<K2>) and Equivalent_Key (@i<K2>, @i<K1>)
+are expected to be equal. If Equivalent_Keys behaves in some other manner, the
+behavior of this package is unspecified. Which subprograms of this package call
+Equivalent_Keys, and how many times they call it, is unspecified.
+
+If the value of a key stored in a node of a map is changed other than by an
+operation in this package such that at least one of Hash or Equivalent_Keys
+give different results, the behavior of this package is unspecified.
+
+Which nodes are the first node and the last node of a map, and which node is the
+successor of a given node, are unspecified, other than the general semantics
+described in A.18.4.
+
+@xcode<@b<procedure> Clear (Container : @b<in out> Map);>
+
+@xindent<In addition to the semantics described in A.18.4, Clear does not
+affect the capacity of Container.>
+
+@xcode<@b<procedure> Insert (Container : @b<in out> Map;
+                  Key       : @b<in>     Key_Type;
+                  New_Item  : @b<in>     Element_Type;
+                  Position  :    @b<out> Cursor;
+                  Inserted  :    @b<out> Boolean);>
+
+@xindent<In addition to the semantics described in A.18.4, if Length
+(Container) equals Capacity (Container), then Insert first calls
+Reserve_Capacity to increase the capacity of Container to some larger value.>
+
+@xcode<@b<function> Equivalent_Keys (Left, Right : Cursor)
+      @b<return> Boolean;>
+
+@xindent<Equivalent to Equivalent_Keys (Key (Left), Key (Right)).>
+
+@xcode<@b<function> Equivalent_Keys (Left  : Cursor;
+                          Right : Key_Type) @b<return> Boolean;>
+
+@xindent<Equivalent to Equivalent_Keys (Key (Left), Right).>
+
+@xcode<@b<function> Equivalent_Keys (Left  : Key_Type;
+                          Right : Cursor) @b<return> Boolean;>
+
+@xindent<Equivalent to Equivalent_Keys (Left, Key (Right)).>
+
+@xcode<@b<function> Capacity (Container : Map) @b<return> Count_Type;>
+
+@xindent<Returns the capacity of Container.>
+
+@xcode<@b<procedure> Reserve_Capacity (Container : @b<in out> Map;
+                            Capacity  : @b<in>     Count_Type);>
+
+@xindent<Reserve_Capacity allocates a new hash table such that the length of the
+resulting map can become at least the value Capacity without requiring an
+additional call to Reserve_Capacity, and is large enough to hold the current
+length of Container. Reserve_Capacity then rehashes the nodes in Container onto
+the new hash table. It replaces the old hash table with the new hash table, and
+then deallocates the old hash table. Any exception raised during allocation is
+propagated and Container is not modified.>
+
+@xindent<Reserve_Capacity tampers with the cursors of Container.>
+
+@i<@s8<Implementation Advice>>
+
+If @i<N> is the length of a map, the average time complexity of the subprograms
+Element, Insert, Include, Replace, Delete, Exclude and Find that take a key
+parameter should be O(log @i<N>). The average time complexity of the
+subprograms that take a cursor parameter should be O(1). The average time
+complexity of Reserve_Capacity should be O(@i<N>).
+
+!corrigendum A.18.6
+
+@dinsc
+
+@i<@s8<Static Semantics>>
+
+The generic library package Containers.Ordered_Maps has the following
+declaration:
+
+@xcode<@b<generic>
+   @b<type> Key_Type @b<is private>;
+   @b<type> Element_Type @b<is private>;
+   @b<with function> "<" (Left, Right : Key_Type) @b<return> Boolean @b<is> <@>;
+   @b<with function> "=" (Left, Right : Element_Type) @b<return> Boolean @b<is> <@>;
+@b<package> Ada.Containers.Ordered_Maps @b<is>
+   @b<pragma> Preelaborate (Ordered_Maps);
+
+   @b<type> Map @b<is tagged private>;
+
+   @b<type> Cursor @b<is private>;
+
+   Empty_Map : @b<constant> Map;
+
+   No_Element : @b<constant> Cursor;
+
+   @b<function> "=" (Left, Right : Map) @b<return> Boolean;
+
+   @b<function> Length (Container : Map) @b<return> Count_Type;
+
+   @b<function> Is_Empty (Container : Map) @b<return> Boolean;
+
+   @b<procedure> Clear (Container : @b<in out> Map);
+
+   @b<function> Key (Position : Cursor) @b<return> Key_Type;
+
+   @b<function> Element (Position : Cursor) @b<return> Element_Type;
+
+   @b<procedure> Query_Element
+     (Position : @b<in> Cursor;
+      Process  : @b<not null access procedure> (Key     : @b<in> Key_Type;
+                                            Element : @b<in> Element_Type));
+
+   @b<procedure> Update_Element
+     (Position : @b<in> Cursor;
+      Process  : @b<not null access procedure> (Key     : @b<in>     Key_Type;
+                                            Element : @b<in out> Element_Type));
+
+   @b<procedure> Replace_Element (Position : @b<in> Cursor;
+                              By       : @b<in> Element_Type);
+
+   @b<procedure> Move (Target : @b<in out> Map;
+                   Source : @b<in out> Map);
+
+   @b<procedure> Insert (Container : @b<in out> Map;
+                     Key       : @b<in>     Key_Type;
+                     New_Item  : @b<in>     Element_Type;
+                     Position  :    @b<out> Cursor;
+                     Inserted  :    @b<out> Boolean);
+
+   @b<procedure> Insert (Container : @b<in out> Map;
+                     Key       : @b<in>     Key_Type;
+                     Position  :    @b<out> Cursor;
+                     Inserted  :    @b<out> Boolean);
+
+   @b<procedure> Insert (Container : @b<in out> Map;
+                     Key       : @b<in>     Key_Type;
+                     New_Item  : @b<in>     Element_Type);
+
+   @b<procedure> Include (Container : @b<in out> Map;
+                      Key       : @b<in>     Key_Type;
+                      New_Item  : @b<in>     Element_Type);
+
+   @b<procedure> Replace (Container : @b<in out> Map;
+                      Key       : @b<in>     Key_Type;
+                      New_Item  : @b<in>     Element_Type);
+
+   @b<procedure> Delete (Container : @b<in out> Map;
+                     Key       : @b<in>     Key_Type);
+
+   @b<procedure> Delete (Container : @b<in out> Map;
+                     Position  : @b<in out> Cursor);
+
+   @b<procedure> Delete_First (Container : @b<in out> Map);
+
+   @b<procedure> Delete_Last (Container : @b<in out> Map);
+
+   @b<procedure> Exclude (Container : @b<in out> Map;
+                      Key       : @b<in>     Key_Type);
+
+   @b<function> Contains (Container : Map;
+                      Key       : Key_Type) @b<return> Boolean;
+
+   @b<function> Find (Container : Map;
+                  Key       : Key_Type) @b<return> Cursor;
+
+   @b<function> Element (Container : Map;
+                     Key       : Key_Type) @b<return> Element_Type;
+
+   @b<function> Floor (Container : Map;
+                   Key       : Key_Type) @b<return> Cursor;
+
+   @b<function> Ceiling (Container : Map;
+                     Key       : Key_Type) @b<return> Cursor;
+
+   @b<function> First (Container : Map) @b<return> Cursor;
+
+   @b<function> First_Key (Container : Map) @b<return> Key_Type;
+
+   @b<function> First_Element (Container : Map) @b<return> Element_Type;
+
+   @b<function> Last (Container : Map) @b<return> Cursor;
+
+   @b<function> Last_Key (Container : Map) @b<return> Key_Type;
+
+   @b<function> Last_Element (Container : Map) @b<return> Element_Type;
+
+   @b<function> Next (Position : Cursor) @b<return> Cursor;
+
+   @b<procedure> Next (Position : @b<in out> Cursor);
+
+   @b<function> Previous (Position : Cursor) @b<return> Cursor;
+
+   @b<procedure> Previous (Position : @b<in out> Cursor);
+
+   @b<function> Has_Element (Position : Cursor) @b<return> Boolean;
+
+   @b<function> "<" (Left, Right : Cursor) @b<return> Boolean;
+
+   @b<function> "@>" (Left, Right : Cursor) @b<return> Boolean;
+
+   @b<function> "<" (Left : Cursor; Right : Key_Type) @b<return> Boolean;
+
+   @b<function> "@>" (Left : Cursor; Right : Key_Type) @b<return> Boolean;
+
+   @b<function> "<" (Left : Key_Type; Right : Cursor) @b<return> Boolean;
+
+   @b<function> "@>" (Left : Key_Type; Right : Cursor) @b<return> Boolean;
+
+   @b<procedure> Iterate
+     (Container : @b<in> Map;
+      Process   : @b<not null access procedure> (Position : @b<in> Cursor));
+
+   @b<procedure> Reverse_Iterate
+     (Container : @b<in> Map;
+      Process   : @b<not null access procedure> (Position : @b<in> Cursor));
+
+@b<private>
+
+   ... -- @ft<@i<not specified by the language>>
+
+@b<end> Ada.Containers.Ordered_Maps;>
+
+Two keys @i<K1> and @i<K2> are @i<equivalent> if both @i<K1> < @i<K2> and
+@i<K2> < @i<K1> return False, using the generic formal "<" operator for
+keys.
+
+Functions "<" and "=" on Key_Type values are expected to return the same result
+value each time they are called with a particular pair of key values. If @i<A> = @i<B>
+returns True, then @i<B> = @i<A> is expected to also return True. If @i<A> < @i<B>
+returns True, then @i<B> < @i<A> is expected to return False. For any two
+equivalent elements, "=" is expected to return True. If "<" or "=" behaves in
+some other manner, the behavior of this package is unspecified. Which
+subprograms of this package call "<" and "=", and how many times these
+functions are called, is unspecified.
+
+If the value of a key stored in a map is changed other than by an operation in
+this package such that at least one of "<" or "=" give different results, the
+behavior of this package is unspecified.
+
+The first node of a nonempty map is the one whose key is less than the key of
+all the other nodes in the map. The last node of a nonempty map is the one
+whose key is greater than the key of all the other elements in the map. The
+successor of a node is the node with the smallest key that is larger than the
+key of the given node. The predecessor of a node is the node with the largest
+key that is smaller than the key of the given node. All comparisons are done
+using the generic formal "<" operator for keys.
+
+@xcode<@b<procedure> Delete_First (Container : @b<in out> Map);>
+
+@xindent<If Container is empty, Delete_First has no effect. Otherwise the node
+designated by First (Container) is removed from Container. Delete_First
+tampers with the cursors of Container.>
+
+@xcode<@b<procedure> Delete_Last (Container : @b<in out> Map);>
+
+@xindent<If Container is empty, Delete_Last has no effect. Otherwise the node designated
+by Last (Container) is removed from Container. Delete_Last tampers with
+the cursors of Container.>
+
+@xcode<@b<function> Floor (Container : Map;
+                Key       : Key_Type) @b<return> Cursor;>
+
+@xindent<Floor searches for the last node whose key is not greater than Key. If such a
+node is found, a cursor that designates it is returned. Otherwise No_Element is
+returned.>
+
+@xcode<@b<function> Ceiling (Container : Map;
+                  Key       : Key_Type) @b<return> Cursor;>
+
+@xindent<Ceiling searches for the first node whose key is not less than Key,
+using the generic formal "<" operator for keys. If such a node is found,
+a cursor that designates it is returned. Otherwise No_Element is returned.>
+
+@xcode<@b<function> First_Key (Container : Map) @b<return> Key_Type;>
+
+@xindent<Equivalent to Key (First (Container)).>
+
+@xcode<@b<function> First_Element (Container : Map) @b<return> Element_Type;>
+
+@xindent<Equivalent to Element (First (Container)).>
+
+@xcode<@b<function> Last (Container : Map) @b<return> Cursor;>
+
+@xindent<Returns a cursor that designates the last node in Container. If Container is
+empty, returns No_Element.>
+
+@xcode<@b<function> Last_Key (Container : Map) @b<return> Key_Type;>
+
+@xindent<Equivalent to Key (Last (Container)).>
+
+@xcode<@b<function> Last_Element (Container : Map) @b<return> Element_Type;>
+
+@xindent<Equivalent to Element (Last (Container)).>
+
+@xcode<@b<function> Previous (Position : Cursor) @b<return> Cursor;>
+
+@xindent<If Position equals No_Element, then Previous returns No_Element. Otherwise
+Previous returns the a cursor designating the node that precedes the one
+designated by Position. If Position designates the first element, then Previous
+returns No_Element.>
+
+@xcode<@b<procedure> Previous (Position : @b<in out> Cursor);>
+
+@xindent<Equivalent to Position := Previous (Position).>
+
+@xcode<@b<function> "<" (Left, Right : Cursor) @b<return> Boolean;>
+
+@xindent<Equivalent to Key (Left) < Key (Right).>
+
+@xcode<@b<function> "@>" (Left, Right : Cursor) @b<return> Boolean;>
+
+@xindent<Equivalent to Key (Right) < Key (Left).>
+
+@xcode<@b<function> "<" (Left : Cursor; Right : Key_Type) @b<return> Boolean;>
+
+@xindent<Equivalent to Key (Left) < Right.>
+
+@xcode<@b<function> "@>" (Left : Cursor; Right : Key_Type) @b<return> Boolean;>
+
+@xindent<Equivalent to Right < Key (Left).>
+
+@xcode<@b<function> "<" (Left : Key_Type; Right : Cursor) @b<return> Boolean;>
+
+@xindent<Equivalent to Left < Key (Right).>
+
+@xcode<@b<function> "@>" (Left : Key_Type; Right : Cursor) @b<return> Boolean;>
+
+@xindent<Equivalent to Key (Right) < Left.>
+
+@xcode<@b<procedure> Reverse_Iterate
+  (Container : @b<in> Map;
+   Process   : @b<not null access procedure> (Position : @b<in> Cursor));>
+
+@xindent<Iterates over the nodes in Container as per Iterate, with the
+difference that the nodes are traversed in predecessor order, starting with the
+last node.>
+
+@i<@s8<Implementation Advice>>
+
+If @i<N> is the length of a map, then the worst-case time complexity of the
+Element, Insert, Include, Replace, Delete, Exclude and Find operations that
+take a key parameter should be O((log @i<N>)**2) or better. The worst-case
+time complexity of the subprograms that take a cursor parameter should be O(1).
+
+!corrigendum A.18.7
+
+@dinsc
+
+The language-defined generic packages Containers.Hashed_Sets and
+Containers.Ordered_Sets provide private types Set and Cursor, and a set of
+operations for each type. A set container allows elements of an arbitrary type
+to be stored without duplication. A hashed set uses a hash function to organize
+elements, while an ordered set orders its element per a specified relation.
+
+This section describes the declarations that are common to both kinds of sets.
+See A.18.8 for a description of the semantics specific to
+Containers.Hashed_Sets and A.18.9 for a description of the semantics specific
+to Containers.Ordered_Sets.
+
+@i<@s8<Static Semantics>>
+
+The type Set is used to represent sets. The type Set needs finalization (see
+7.6).
+
+A set contains elements. Set cursors designate elements. There exists an
+equivalence relation on elements, whose definition is different for hashed sets
+and ordered sets. A set never contains two or more equivalent elements. The
+@i<length> of a set is the number of elements it contains.
+
+Each nonempty set has two particular elements called the @i<first element> and
+the @i<last element> (which may be the same). Each element except for the last
+element has a @i<successor element>. If there are no other intervening
+operations, starting with the first element and repeatedly going to the
+successor element will visit each element in the map exactly once until the
+last element is reached. The exact definition of these terms is different for
+hashed sets and ordered sets.
+
+Some operations are assumed to work on a constant set of elements. For such
+an operation, a subprogram is said to @i<tamper with cursors> of a set object
+@i<S> if:
+
+@xbullet<it inserts or deletes elements of @i<S>, that is, it calls the Insert,
+Include, Clear, Delete, Exclude, or Replace_Element procedures with S as
+a parameter; or>
+
+@xbullet<it finalizes @i<S>; or>
+
+@xbullet<it calls the Move procedure with @i<S> as a parameter; or>
+
+@xbullet<it calls one of the operations defined to tamper with cursors of @i<S>.>
+
+Some operations are assumed to not change elements. For such an operation, a
+subprogram is said to @i<tamper with elements> of a set object @i<S> if:
+
+@xbullet<it tampers with cursors of @i<S>; or>
+
+@xbullet<it modifies one or more elements of @i<S>, that is, it calls the
+Replace or Update_Element_Preserving_Key procedures with @i<S> as a
+parameter.>
+
+Empty_Set represents the empty Set object. It has a length of 0. If an object
+of type Set is not otherwise initialized, it is initialized to the same
+value as Empty_Set.
+
+No_Element represents a cursor that designates no element. If an object of type
+Cursor is not otherwise initialized, it is initialized to the same
+value as No_Element.
+
+@xcode<@b<function> "=" (Left, Right : Set) @b<return> Boolean;>
+
+@xindent<If Left and Right denote the same set object, then the function returns True.
+If Left and Right have different lengths, then the function returns False.
+Otherwise, for each element @i<E> in Left, the function returns False if an element
+equal to @i<E> (in the sense of the generic formal equality operator) is not
+present in Right. If the function has not returned a result after checking all
+of the elements, it returns True. Any exception raised during evaluation of
+element equality is propagated.>
+
+@xcode<@b<function> Equivalent_Sets (Left, Right : Set) @b<return> Boolean;>
+
+@xindent<If Left and Right denote the same set object, then the function
+returns True. If Left and Right have different lengths, then the function
+returns False. Otherwise, for each element @i<E> in Left, the function returns
+False if an element equivalent to @i<E> is not present in Right. If the
+function has not returned a result after checking all of the elements, it
+returns True. Any exception raised during evaluation of element equivalence is
+propagated.>
+
+@xcode<@b<function> Length (Container : Set) @b<return> Count_Type;>
+
+@xindent<Returns the number of elements in Container.>
+
+@xcode<@b<function> Is_Empty (Container : Set) @b<return> Boolean;>
+
+@xindent<Equivalent to Length (Container) = 0.>
+
+@xcode<@b<procedure> Clear (Container : @b<in out> Set);>
+
+@xindent<Removes all the elements from Container.>
+
+@xcode<@b<function> Element (Position : Cursor) @b<return> Element_Type;>
+
+@xindent<If Position equals No_Element, then Constraint_Error is propagated.
+Otherwise, Element returns the element designated by Position.>
+
+@xcode<@b<procedure> Query_Element
+  (Position : @b<in> Cursor;
+   Process  : @b<not null access procedure> (Element : @b<in> Element_Type));>
+
+@xindent<If Position equals No_Element, then Constraint_Error is propagated.
+Otherwise, Query_Element calls Process.@b<all> with the element designated by
+Position as the argument. Program_Error is propagated if Process.@b<all>
+tampers with the elements of Container. Any exceptions raised by
+Process.@b<all> are propagated.>
+
+@xcode<@b<procedure> Replace_Element (Container : @b<in> Set;
+                           Position  : @b<in> Cursor;
+                           By        : @b<in> Element_Type);>
+
+@xindent<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.>
+
+@xcode<@b<procedure> Move (Target : @b<in out> Set;
+                Source : @b<in out> Set);>
+
+@xindent<If Target denotes the same object as Source, then Move has no effect.
+Otherwise, Move first clears Target. Then, each element from Source is removed
+from Source and inserted into Target. The length of Source is 0 after a
+successful call to Move.>
+
+@xcode<@b<procedure> Insert (Container : @b<in out> Set;
+                  New_Item  : @b<in>     Element_Type;
+                  Position  :    @b<out> Cursor;
+                  Inserted  :    @b<out> Boolean);>
+
+@xindent<Insert checks if an element equivalent to New_Item is already present
+in Container. If a match is found, Inserted is set to False and Position
+designates the matching element. Otherwise, Insert adds New_Item to Container;
+Inserted is set to True and Position designates the newly-inserted element. Any
+exception raised during allocation is propagated and Container is not
+modified.>
+
+@xcode<@b<procedure> Insert (Container : @b<in out> Set;
+                  New_Item  : @b<in>     Element_Type);>
+
+@xindent<Insert inserts New_Item into Container as per the four-parameter
+Insert, with the difference that if an element equivalent to New_Item is
+already in the set, then Constraint_Error is propagated.>
+
+@xcode<@b<procedure> Include (Container : @b<in out> Set;
+                   New_Item  : @b<in>     Element_Type);>
+
+@xindent<Include inserts New_Item into Container as per the four-parameter
+Insert, with the difference that if an element equivalent to New_Item is
+already in the set, then it is replaced. Any exception raised during assignment
+is propagated.>
+
+@xcode<@b<procedure> Replace (Container : @b<in out> Set;
+                   New_Item  : @b<in>     Element_Type);>
+
+@xindent<Replace checks if an element equivalent to New_Item is already in the
+set. If a match is found, that element is replaced with New_Item; otherwise,
+Constraint_Error is propagated.>
+
+@xcode<@b<procedure> Delete (Container : @b<in out> Set;
+                  Item      : @b<in>     Element_Type);>
+
+@xindent<Delete checks if an element equivalent to Item is present in
+Container. If a match is found, Delete removes the element from the set;
+otherwise, Constraint_Error is propagated.>
+
+@xcode<@b<procedure> Delete (Container : @b<in out> Set;
+                  Position  : @b<in out> Cursor);>
+
+@xindent<If Position equals No_Element, Delete has no effect. If Position does
+not designate an element in Container, then Program_Error is propagated.
+Otherwise, Delete removes the node designated by Position from the set.
+Position is set to No_Element on return.>
+
+@xcode<@b<procedure> Exclude (Container : @b<in out> Set;
+                   Item      : @b<in>     Element_Type);>
+
+@xindent<Exclude checks if an element equivalent to Item is present in
+Container. If a match is found, Exclude removes the element from the set.>
+
+@xcode<@b<function> Contains (Container : Set;
+                   Item      : Element_Type) @b<return> Boolean;>
+
+@xindent<Equivalent to Find (Container, Item) /= No_Element.>
+
+@xcode<@b<function> Find (Container : Set;
+               Item      : Element_Type) @b<return> Cursor;>
+
+@xindent<If Length (Container) equals 0, then Find returns No_Element.
+Otherwise, Find checks if an element equivalent to Item is present in
+Container. If a match is found, a cursor designating the matching element is
+returned; otherwise, No_Element is returned.>
+
+@xcode<@b<function> First (Container : Set) @b<return> Cursor;>
+
+@xindent<If Length (Container) = 0, then First returns No_Element. Otherwise, First
+returns a cursor that designates the first node in Container.>
+
+@xcode<@b<function> Next (Position  : Cursor) @b<return> Cursor;>
+
+@xindent<Returns a cursor that designates the successor of the element
+designated by Position. If Position designates the last element, then
+No_Element is returned. If Position equals No_Element, then No_Element is
+returned.>
+
+@xcode<@b<procedure> Next (Position  : @b<in out> Cursor);>
+
+@xindent<Equivalent to Position := Next (Position).>
+
+@xcode<@b<function> Has_Element (Position : Cursor) @b<return> Boolean;>
+
+@xindent<Returns True if Position designates an element, and returns False otherwise.>
+
+@xcode<@b<procedure> Iterate
+  (Container : @b<in> Set;
+   Process   : @b<not null access procedure> (Position : @b<in> Cursor));>
+
+@xindent<Iterate calls Process.@b<all> with a cursor that designates each
+element in Container, starting with the first node and moving the cursor
+according to the successor relation. Program_Error is propagated if
+Process.@b<all> tampers with the elements of Container. Any exception raised by
+Process.@b<all> is propagated.>
+
+@xcode<@b<procedure> Union (Target : @b<in out> Set;
+                 Source : @b<in>     Set);>
+
+@xindent<Union inserts into Target the elements of Source that are not equivalent to
+some element already in Target.>
+
+@xcode<@b<function> Union (Left, Right : Set) @b<return> Set;>
+
+@xindent<Returns a set comprising all of the elements of Left, and the elements of Right
+that are not equivalent to some element of Left.>
+
+@xcode<@b<procedure> Intersection (Target : @b<in out> Set;
+                        Source : @b<in>     Set);>
+
+@xindent<Union deletes from Target the elements of Target that are not equivalent to
+some element of Source.>
+
+@xcode<@b<function> Intersection (Left, Right : Set) @b<return> Set;>
+
+@xindent<Returns a set comprising all the elements of Left that are equivalent to
+the some element of Right.>
+
+@xcode<@b<procedure> Difference (Target : @b<in out> Set;
+                      Source : @b<in>     Set);>
+
+@xindent<If Target denotes the same object as Source, then Difference clears
+Target. Otherwise, it deletes from Target the elements that are equivalent to
+some element of Source.>
+
+@xcode<@b<function> Difference (Left, Right : Set) @b<return> Set;>
+
+@xindent<Returns a set comprising the elements of Left that are not equivalent
+to some element of Right.>
+
+@xcode<@b<procedure> Symmetric_Difference (Target : @b<in out> Set;
+                                Source : @b<in>     Set);>
+
+@xindent<If Target denotes the same object as Source, then Symmetric_Difference
+clears Target. Otherwise, it deletes from Target the elements that are
+equivalent to some element of Source, and inserts into Target the elements of
+Source that are not equivalent to some element of Target.>
+
+@xcode<@b<function> Symmetric_Difference (Left, Right : Set) @b<return> Set;>
+
+@xindent<Returns a set comprising the elements of Left that are not equivalent
+to some element of Right, and the elements of Right that are not equivalent to
+some element of Left.>
+
+@xcode<@b<function> Overlap (Left, Right : Set) @b<return> Boolean;>
+
+@xindent<If an element of Left is equivalent to some element of Right, then
+Overlap returns True. Otherwise it returns False.>
+
+@xcode<@b<function> Is_Subset (Subset : Set;
+                    Of_Set : Set) @b<return> Boolean;>
+
+@xindent<If an element of Subset is not equivalent to some element of Of_Set,
+then Is_Subset returns False. Otherwise it returns True.>
+
+Both Containers.Hashed_Set and Containers.Ordered_Set declare a nested generic
+package Generic_Keys, which provides operations that allow set manipulation in
+terms of a key (typically, a portion of an element) instead of a complete
+element. The formal function Key of Generic_Keys extracts a key value from an
+element. It is expected to return the same value each time it is called with a
+particular element. The behavior of Generic_Keys is unspecified if Key behaves
+in some other manner.
+
+A key is expected to unambiguously determine one equivalence class for elements.
+The behavior of Generic_Keys is unspecified if the formal parameters of this
+package behave in some other manner.
+
+The subprograms in package Generic_Keys named Contains, Find, Element, Delete,
+and Exclude, are equivalent to the corresponding subprograms in the parent
+package, with the difference that the Key parameter is used locate an element
+in the set.
+
+@xcode<@b<procedure> Replace (Container : @b<in out> Set;
+                   Key       : @b<in>     Key_Type;
+                   New_Item  : @b<in>     Element_Type);>
+
+@xindent<Equivalent to Replace_Element (Container, Find (Container, Key), New_Item).>
+
+@xcode<@b<function> Key (Position : Cursor) @b<return> Key_Type;>
+
+@xindent<Equivalent to Key (Element (Position)).>
+
+@xcode<@b<procedure> Update_Element_Preserving_Key
+  (Container : @b<in out> Set;
+   Position  : @b<in>     Cursor;
+   Process   : @b<not null access procedure>
+                                 (Element : @b<in out> Element_Type));>
+
+@xindent<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, Update_Element_Preserving_Key uses Key to save the key
+value K of the element designated by Position. Update_Element_Preserving_Key
+then calls Process.@b<all> with that element as the argument. Program_Error is
+propagated if Process.@b<all> tampers with the elements of Container. Any
+exception raised by Process.@b<all> is propagated. After Process.@b<all>
+returns, Update_Element_Preserving_Key checks if K determines the same
+equivalence class as that for the new element; if not, the element is removed
+from the set and Program_Error is propagated.>
+
+@xindent<If Element_Type is unconstrained and definite, then the Element
+parameter of Process.@b<all> shall be unconstrained.>
+
+@i<@s8<Erroneous Execution>>
+
+A Cursor value is @i<invalid> if any of the following have occurred since it
+was created:
+@xbullet<The set that contains the element it designates has been finalized;>
+@xbullet<The set that contains the element it designates has been used as the
+Source or Target of a call to Move;>
+@xbullet<The element it designates has been deleted from the set.>
+
+The result of "=" or Has_Element is unspecified if these functions are called
+with an invalid cursor parameter. Execution is erroneous if any other
+subprogram declared in Containers.Hashed_Sets or Containers.Ordered_Sets is
+called with an invalid cursor parameter.
+
+@i<@s8<Implementation Requirements>>
+
+No storage associated with a Set object shall be lost upon assignment or scope
+exit.
+
+@i<@s8<Implementation Advice>>
+
+Move should not copy elements, and should minimize copying of internal
+data structures.
+
+!corrigendum A.18.8
+
+@dinsc
+
+@i<@s8<Static Semantics>>
+
+The generic library package Containers.Hashed_Sets has the following
+declaration:
+
+@xcode<@b<generic>
+   @b<type> Element_Type @b<is private>;
+   @b<with function> Hash (Element : Element_Type) @b<return> Hash_Type;
+   @b<with function> Equivalent_Elements (Left, Right : Element_Type)
+                 @b<return> Boolean;
+   @b<with function> "=" (Left, Right : Element_Type) @b<return> Boolean @b<is> <@>;
+@b<package> Ada.Containers.Hashed_Sets @b<is>
+   @b<pragma> Preelaborate (Hashed_Sets);
+
+   @b<type> Set @b<is tagged private>;
+
+   @b<type> Cursor @b<is private>;
+
+   Empty_Set : @b<constant> Set;
+
+   No_Element : @b<constant> Cursor;
+
+   @b<function> "=" (Left, Right : Set) @b<return> Boolean;
+
+   @b<function> Equivalent_Sets (Left, Right : Set) @b<return> Boolean;
+
+   @b<function> Length (Container : Set) @b<return> Count_Type;
+
+   @b<function> Is_Empty (Container : Set) @b<return> Boolean;
+
+   @b<procedure> Clear (Container : @b<in out> Set);
+
+   @b<function> Element (Position : Cursor) @b<return> Element_Type;
+
+   @b<procedure> Query_Element
+     (Position : @b<in> Cursor;
+      Process  : @b<not null access procedure> (Element : @b<in> Element_Type));
+
+   @b<procedure> Replace_Element (Container : @b<in> Set;
+                              Position  : @b<in> Cursor;
+                              By        : @b<in> Element_Type);
+
+   @b<procedure> Move (Target : @b<in out> Set;
+                   Source : @b<in out> Set);
+
+   @b<procedure> Insert (Container : @b<in out> Set;
+                     New_Item  : @b<in>     Element_Type;
+                     Position  :    @b<out> Cursor;
+                     Inserted  :    @b<out> Boolean);
+
+   @b<procedure> Insert (Container : @b<in out> Set;
+                     New_Item  : @b<in>     Element_Type);
+
+   @b<procedure> Include (Container : @b<in out> Set;
+                      New_Item  : @b<in>     Element_Type);
+
+   @b<procedure> Replace (Container : @b<in out> Set;
+                      New_Item  : @b<in>     Element_Type);
+
+   @b<procedure> Delete (Container : @b<in out> Set;
+                     Item      : @b<in>     Element_Type);
+
+   @b<procedure> Delete (Container : @b<in out> Set;
+                     Position  : @b<in out> Cursor);
+
+   @b<procedure> Exclude (Container : @b<in out> Set;
+                      Item      : @b<in>     Element_Type);
+
+   @b<function> Contains (Container : Set;
+                      Item      : Element_Type) @b<return> Boolean;
+
+   @b<function> Find (Container : Set;
+                  Item      : Element_Type) @b<return> Cursor;
+
+   @b<function> First (Container : Set) @b<return> Cursor;
+
+   @b<function> Next (Position : Cursor) @b<return> Cursor;
+
+   @b<procedure> Next (Position : @b<in out> Cursor);
+
+   @b<function> Has_Element (Position : Cursor) @b<return> Boolean;
+
+   @b<function> Equivalent_Elements (Left, Right : Cursor)
+     @b<return> Boolean;
+
+   @b<function> Equivalent_Elements (Left  : Cursor;
+                                 Right : Element_Type)
+    @b<return> Boolean;
+
+   @b<function> Equivalent_Elements (Left  : Element_Type;
+                                 Right : Cursor)
+    @b<return> Boolean;
+
+   @b<procedure> Iterate
+     (Container : @b<in> Set;
+      Process   : @b<not null access procedure> (Position : @b<in> Cursor));
+
+   @b<procedure> Union (Target : @b<in out> Set;
+                    Source : @b<in>     Set);
+
+   @b<function> Union (Left, Right : Set) @b<return> Set;
+
+   @b<function> "or" (Left, Right : Set) @b<return> Set @b<renames> Union;
+
+   @b<procedure> Intersection (Target : @b<in out> Set;
+                           Source : @b<in>     Set);
+
+   @b<function> Intersection (Left, Right : Set) @b<return> Set;
+
+   @b<function> "and" (Left, Right : Set) @b<return> Set @b<renames> Intersection;
+
+   @b<procedure> Difference (Target : @b<in out> Set;
+                         Source : @b<in>     Set);
+
+   @b<function> Difference (Left, Right : Set) @b<return> Set;
+
+   @b<function> "-" (Left, Right : Set) @b<return> Set @b<renames> Difference;
+
+   @b<procedure> Symmetric_Difference (Target : @b<in out> Set;
+                                   Source : @b<in>     Set);
+
+   @b<function> Symmetric_Difference (Left, Right : Set) @b<return> Set;
+
+   @b<function> "xor" (Left, Right : Set) @b<return> Set
+     @b<renames> Symmetric_Difference;
+
+   @b<function> Overlap (Left, Right : Set) @b<return> Boolean;
+
+   @b<function> Is_Subset (Subset : Set;
+                       Of_Set : Set) @b<return> Boolean;
+
+   @b<function> Capacity (Container : Set) @b<return> Count_Type;
+
+   @b<procedure> Reserve_Capacity (Container : @b<in out> Set;
+                               Capacity  : @b<in>     Count_Type);
+
+   @b<generic>
+      @b<type> Key_Type (<@>) @b<is limited private>;
+      @b<with function> Key (Element : @b<in> Element_Type) @b<return> Key_Type;
+      @b<with function> Hash (Key : Key_Type) @b<return> Hash_Type;
+      @b<with function> Equivalent_Keys (Left : Key_Type; Right : Element_Type)
+                                     @b<return> Boolean;
+   @b<package> Generic_Keys @b<is>
+
+      @b<function> Contains (Container : Set;
+                         Key       : Key_Type)
+         @b<return> Boolean;
+
+      @b<function> Find (Container : Set;
+                     Key       : Key_Type)
+         @b<return> Cursor;
+
+      @b<function> Key (Position : Cursor) @b<return> Key_Type;
+
+      @b<function> Element (Container : Set;
+                        Key       : Key_Type)
+        @b<return> Element_Type;
+
+      @b<procedure> Replace (Container : @b<in out> Set;
+                         Key       : @b<in>     Key_Type;
+                         New_Item  : @b<in>     Element_Type);
+
+      @b<procedure> Delete (Container : @b<in out> Set;
+                        Key       : @b<in>     Key_Type);
+
+      @b<procedure> Exclude (Container : @b<in out> Set;
+                         Key       : @b<in>     Key_Type);
+
+      @b<procedure> Update_Element_Preserving_Key
+        (Container : @b<in out> Set;
+         Position  : @b<in>     Cursor;
+         Process   : @b<not null access procedure>
+                                       (Element : @b<in out> Element_Type));
+
+      @b<function> Equivalent_Keys (Left  : Cursor;
+                                Right : Key_Type)
+        @b<return> Boolean;
+
+      @b<function> Equivalent_Keys (Left  : Key_Type;
+                                Right : Cursor)
+        @b<return> Boolean;
+
+   @b<end> Generic_Keys;
+
+@b<private>
+
+   ... -- @ft<@i<not specified by the language>>
+
+@b<end> Ada.Containers.Hashed_Sets;>
+
+An object of type Set contains an expandable hash table, which is used to
+provide direct access to elements. The @i<capacity> of an object of type Set is
+the maximum number of elements that can be inserted into the hash table prior
+to it being automatically expanded.
+
+Two elements @i<E1> and @i<E2> are defined to be @i<equivalent> if
+Equivalent_Elements (@i<E1>, @i<E2>) returns True.
+
+Function Hash is expected to return the same value each time it is called with
+a particular element value. For any two equivalent elements, Hash is expected
+to return the same value. If Hash behaves in some other manner, the behavior of
+this package is unspecified. Which subprograms of this package call Hash, and
+how many times they call it, is unspecified.
+
+Function Equivalent_Elements is expected to return the same value each time
+it is called with a particular pair of element values. For any two elements @i<E1>
+and @i<E2>, the boolean values Equivalent_Elements (@i<E1>, @i<E2>) and
+Equivalent_Elements (@i<E2>, @i<E1>)
+are expected to be equal. If Equivalent_Elements behaves in some other manner,
+the behavior of this package is unspecified. Which subprograms of this package
+call Equivalent_Elements, and how many times they call it, is unspecified.
+
+If the value of an element stored in a set is changed other than by an
+operation in this package such that at least one of Hash or Equivalent_Elements
+give different results, the behavior of this package is unspecified.
+
+Which elements are the first element and the last element of a set, and which
+element is the successor of a given element, are unspecified, other than the
+general semantics described in A.18.7.
+
+@xcode<@b<procedure> Clear (Container : @b<in out> Set);>
+
+@xindent<In addition to the semantics described in A.18.7, Clear does not
+affect the capacity of Container.>
+
+@xcode<@b<procedure> Insert (Container : @b<in out> Set;
+                  New_Item  : @b<in>     Element_Type;
+                  Position  :    @b<out> Cursor;
+                  Inserted  :    @b<out> Boolean);>
+
+@xindent<In addition to the semantics described in A.18.7, if Length
+(Container) equals Capacity (Container), then Insert first calls
+Reserve_Capacity to increase the capacity of Container to some larger value.>
+
+@xcode<@b<function> First (Container : Set) @b<return> Cursor;>
+
+@xindent<If Length (Container) = 0, then First returns No_Element. Otherwise,
+First returns a cursor that designates the first hashed element in Container.>
+
+@xcode<@b<function> Equivalent_Elements (Left, Right : Cursor)
+      @b<return> Boolean;>
+
+@xindent<Equivalent to Equivalent_Elements (Element (Left), Element (Right)).>
+
+@xcode<@b<function> Equivalent_Elements (Left  : Cursor;
+                              Right : Element_Type) @b<return> Boolean;>
+
+@xindent<Equivalent to Equivalent_Elements (Element (Left), Right).>
+
+@xcode<@b<function> Equivalent_Elements (Left  : Element_Type;
+                              Right : Cursor) @b<return> Boolean;>
+
+@xindent<Equivalent to Equivalent_Elements (Left, Element (Right)).>
+
+@xcode<@b<function> Capacity (Container : Set) @b<return> Count_Type;>
+
+@xindent<Returns the capacity of Container.>
+
+@xcode<@b<procedure> Reserve_Capacity (Container : @b<in out> Set;
+                            Capacity  : @b<in>     Count_Type);>
+
+@xindent<Reserve_Capacity allocates a new hash table such that the length of the
+resulting set can become at least the value Capacity without requiring an
+additional call to Reserve_Capacity, and is large enough to hold the current
+length of Container. Reserve_Capacity then rehashes the nodes in Container onto
+the new hash table. It replaces the old hash table with the new hash table, and
+then deallocates the old hash table. Any exception raised during allocation is
+propagated and Container is not modified.>
+
+@xindent<Reserve_Capacity tampers with the cursors of Container.>
+
+For any element @i<E>, the function Generic_Keys.Hash must be such that
+Hash (@i<E>) = Generic_Keys.Hash (Key (@i<E>)). If Key or Generic_Keys.Hash
+behave in some other manner, the behavior of Generic_Keys is unspecified. Which
+subprograms of Generic_Keys call Generic_Keys.Hash, and how many times they
+call it, is unspecified.
+
+For any two elements @i<E1> and @i<E2>, the boolean values
+Equivalent_Element (@i<E1>, @i<E2>), Equivalent_Keys (Key (@i<E1>), @i<E2>),
+and Equivalent_Keys (Key (@i<E2>), @i<E1>) are all expected to be equal. If Key
+or Equivalent behave in some other manner, the behavior of Generic_Keys is
+unspecified. Which subprograms of Generic_Keys call Equivalent, and how many
+times they call it, is unspecified.
+
+@xcode<@b<function> Equivalent_Keys (Left  : Cursor;
+                          Right : Key_Type) @b<return> Boolean;>
+
+@xindent<Equivalent to Equivalent_Keys (Key (Left), Right).>
+
+@xcode<@b<function> Equivalent_Keys (Left  : Key_Type;
+                          Right : Cursor) @b<return> Boolean;>
+
+@xindent<Equivalent to Equivalent_Keys (Left, Key (Right)).>
+
+@i<@s8<Implementation Advice>>
+
+If @i<N> is the length of a set, the average time complexity of the subprograms
+Insert, Include, Replace, Delete, Exclude and Find that take an element
+parameter should be O(log @i<N>). The average time complexity of the
+subprograms that take a cursor parameter should be O(1). The average time
+complexity of Reserve_Capacity should be O(@i<N>).
+
+!corrigendum A.18.9
+
+@dinsc
+
+@i<@s8<Static Semantics>>
+
+The generic library package Containers.Ordered_Sets has the following
+declaration:
+
+@xcode<@b<generic>
+   @b<type> Element_Type @b<is private>;
+   @b<with function> "<" (Left, Right : Element_Type) @b<return> Boolean @b<is> <@>;
+   @b<with function> "=" (Left, Right : Element_Type) @b<return> Boolean @b<is> <@>;
+@b<package> Ada.Containers.Ordered_Sets @b<is>
+   @b<pragma> Preelaborate (Ordered_Sets);
+
+   @b<type> Set @b<is tagged private;>
+
+   @b<type> Cursor @b<is private>;
+
+   Empty_Set : @b<constant> Set;
+
+   No_Element : @b<constant> Cursor;
+
+   @b<function> "=" (Left, Right : Set) @b<return> Boolean;
+
+   @b<function> Equivalent_Sets (Left, Right : Set) @b<return> Boolean;
+
+   @b<function> Length (Container : Set) @b<return> Count_Type;
+
+   @b<function> Is_Empty (Container : Set) @b<return> Boolean;
+
+   @b<procedure> Clear (Container : @b<in out> Set);
+
+   @b<function> Element (Position : Cursor) @b<return> Element_Type;
+
+   @b<procedure> Query_Element
+     (Position : @b<in> Cursor;
+      Process  : @b<not null access procedure> (Element : @b<in> Element_Type));
+
+   @b<procedure> Replace_Element (Container : @b<in> Set;
+                              Position  : @b<in> Cursor;
+                              By        : @b<in> Element_Type);
+
+   @b<procedure> Move (Target : @b<in out> Set;
+                   Source : @b<in out> Set);
+
+   @b<procedure> Insert (Container : @b<in out> Set;
+                     New_Item  : @b<in>     Element_Type;
+                     Position  :    @b<out> Cursor;
+                     Inserted  :    @b<out> Boolean);
+
+   @b<procedure> Insert (Container : @b<in out> Set;
+                     New_Item  : @b<in>     Element_Type);
+
+   @b<procedure> Include (Container : @b<in out> Set;
+                      New_Item  : @b<in>     Element_Type);
+
+   @b<procedure> Replace (Container : @b<in out> Set;
+                      New_Item  : @b<in>     Element_Type);
+
+   @b<procedure> Delete (Container : @b<in out> Set;
+                     Item      : @b<in>     Element_Type);
+
+   @b<procedure> Exclude (Container : @b<in out> Set;
+                      Item      : @b<in>     Element_Type);
+
+   @b<procedure> Delete (Container : @b<in out> Set;
+                     Position  : @b<in out> Cursor);
+
+   @b<procedure> Delete_First (Container : @b<in out> Set);
+
+   @b<procedure> Delete_Last (Container : @b<in out> Set);
+
+   @b<procedure> Union (Target : @b<in out> Set;
+                    Source : @b<in>     Set);
+
+   @b<function> Union (Left, Right : Set) @b<return> Set;
+
+   @b<function> "or" (Left, Right : Set) @b<return> Set @b<renames> Union;
+
+   @b<procedure> Intersection (Target : @b<in out> Set;
+                           Source : @b<in>     Set);
+
+   @b<function> Intersection (Left, Right : Set) @b<return> Set;
+
+   @b<function> "and" (Left, Right : Set) @b<return> Set @b<renames> Intersection;
+
+   @b<procedure> Difference (Target : @b<in out> Set;
+                         Source : @b<in>     Set);
+
+   @b<function> Difference (Left, Right : Set) @b<return> Set;
+
+   @b<function> "-" (Left, Right : Set) @b<return> Set @b<renames> Difference;
+
+   @b<procedure> Symmetric_Difference (Target : @b<in out> Set;
+                                   Source : @b<in>     Set);
+
+   @b<function> Symmetric_Difference (Left, Right : Set) @b<return> Set;
+
+   @b<function> "xor" (Left, Right : Set) @b<return> Set @b<renames>
+      Symmetric_Difference;
+
+   @b<function> Overlap (Left, Right : Set) @b<return> Boolean;
+
+   @b<function> Is_Subset (Subset : Set;
+                       Of_Set : Set) @b<return> Boolean;
+
+   @b<function> Contains (Container : Set;
+                      Item      : Element_Type) @b<return> Boolean;
+
+   @b<function> Find (Container : Set;
+                  Item      : Element_Type)
+      @b<return> Cursor;
+
+   @b<function> Floor (Container : Set;
+                   Item      : Element_Type)
+      @b<return> Cursor;
+
+   @b<function> Ceiling (Container : Set;
+                     Item      : Element_Type)
+      @b<return> Cursor;
+
+   @b<function> First (Container : Set) @b<return> Cursor;
+
+   @b<function> First_Element (Container : Set) @b<return> Element_Type;
+
+   @b<function> Last (Container : Set) @b<return> Cursor;
+
+   @b<function> Last_Element (Container : Set) @b<return> Element_Type;
+
+   @b<function> Next (Position : Cursor) @b<return> Cursor;
+
+   @b<procedure> Next (Position : @b<in out> Cursor);
+
+   @b<function> Previous (Position : Cursor) @b<return> Cursor;
+
+   @b<procedure> Previous (Position : @b<in out> Cursor);
+
+   @b<function> Has_Element (Position : Cursor) @b<return> Boolean;
+
+   @b<function> "<" (Left, Right : Cursor) @b<return> Boolean;
+
+   @b<function> "@>" (Left, Right : Cursor) @b<return> Boolean;
+
+   @b<function> "<" (Left : Cursor; Right : Element_Type)
+      @b<return> Boolean;
+
+   @b<function> "@>" (Left : Cursor; Right : Element_Type)
+      @b<return> Boolean;
+
+   @b<function> "<" (Left : Element_Type; Right : Cursor)
+      @b<return> Boolean;
+
+   @b<function> "@>" (Left : Element_Type; Right : Cursor)
+      @b<return> Boolean;
+
+   @b<procedure> Iterate
+     (Container : @b<in> Set;
+      Process   : @b<not null access procedure> (Position : @b<in> Cursor));
+
+   @b<procedure> Reverse_Iterate
+     (Container : @b<in> Set;
+      Process   : @b<not null access procedure> (Position : @b<in> Cursor));
+
+   @b<generic>
+      @b<type> Key_Type (<@>) @b<is limited private>;
+      @b<with function> Key (Element : Element_Type) @b<return> Key_Type;
+      @b<with function> "<" (Left : Key_Type; Right : Element_Type)
+         @b<return> Boolean @b<is> <@>;
+      @b<with function> "@>" (Left : Key_Type; Right : Element_Type)
+         @b<return> Boolean @b<is> <@>;
+   @b<package> Generic_Keys @b<is>
+
+       @b<function> Contains (Container : Set;
+                          Key       : Key_Type) @b<return> Boolean;
+
+       @b<function> Find (Container : Set;
+                      Key       : Key_Type)
+          @b<return> Cursor;
+
+       @b<function> Floor (Container : Set;
+                       Item      : Key_Type)
+          @b<return> Cursor;
+
+       @b<function> Ceiling (Container : Set;
+                         Item      : Key_Type)
+          @b<return> Cursor;
+
+       @b<function> Key (Position : Cursor) @b<return> Key_Type;
+
+       @b<function> Element (Container : Set;
+                         Key       : Key_Type)
+          @b<return> Element_Type;
+
+       @b<procedure> Replace (Container : @b<in out> Set;
+                          Key       : @b<in>     Key_Type;
+                          New_Item  : @b<in>     Element_Type);
+
+       @b<procedure> Delete (Container : @b<in out> Set;
+                         Key       : @b<in>     Key_Type);
+
+       @b<procedure> Exclude (Container : @b<in out> Set;
+                          Key       : @b<in>     Key_Type);
+
+       @b<function> "<" (Left : Cursor; Right : Key_Type)
+          @b<return> Boolean;
+
+       @b<function> "@>" (Left : Cursor; Right : Key_Type)
+          @b<return> Boolean;
+
+       @b<function> "<" (Left : Key_Type; Right : Cursor)
+          @b<return> Boolean;
+
+       @b<function> "@>" (Left : Key_Type; Right : Cursor)
+          @b<return> Boolean;
+
+       @b<procedure> Update_Element_Preserving_Key
+         (Container : @b<in out> Set;
+          Position  : @b<in>     Cursor;
+          Process   : @b<not null access procedure>
+                                         (Element : @b<in out> Element_Type));
+
+   @b<end> Generic_Keys;
+
+@b<private>
+
+   ... -- @ft<@i<not specified by the language>>
+
+@b<end> Ada.Containers.Ordered_Sets;>
+
+Two elements @i<E1> and @i<E2> are @i<equivalent> if both @i<E1> < @i<E2> and
+@i<E2> < @i<E1> return False, using the generic formal "<" operator for
+elements.
+
+Functions "<" and "=" on Element_Type values are expected to return the same
+result value each time they are called with a particular pair of element values.
+If @i<A> = @i<B> returns True, then @i<B> = @i<A> is expected to also return
+True. If @i<A> < @i<B> returns True, then @i<B> < @i<A> is expected to return
+False. For any two equivalent elements, "=" is expected to return True. If "<"
+or "=" behaves in some other manner, the behavior of this package is
+unspecified. Which subprograms of this package call "<" and "=", and how many
+times these functions are called, is unspecified.
+
+If the value of an element stored in a set is changed other than by an
+operation in this package such that at least one of "<" or "=" give different
+results, the behavior of this package is unspecified.
+
+The first element of a nonempty set is the one which is less than all the other
+elements in the set. The last element of a nonempty set is the one which is
+greater than all the other elements in the set. The successor of an element is
+the smallest element that is larger than the given element. The predecessor of
+an element is the largest element that is smaller than the given element. All
+comparisons are done using the generic formal "<" operator for elements.
+
+@xcode<@b<procedure> Delete_First (Container : @b<in out> Set);>
+
+@xindent<If Container is empty, Delete_First has no effect. Otherwise the element
+designated by First (Container) is removed from Container. Delete_First
+tampers with the cursors of Container.>
+
+@xcode<@b<procedure> Delete_Last (Container : @b<in out> Set);>
+
+@xindent<If Container is empty, Delete_Last has no effect. Otherwise the
+element designated by Last (Container) is removed from Container. Delete_Last
+tampers with the cursors of Container.>
+
+@xcode<@b<function> Floor (Container : Set;
+                Item      : Element_Type) @b<return> Cursor;>
+
+@xindent<Floor searches for the last element which is not greater than Item. If
+such an element is found, a cursor that designates it is returned. Otherwise
+No_Element is returned.>
+
+@xcode<@b<function> Ceiling (Container : Set;
+                  Item      : Element_Type) @b<return> Cursor;>
+
+@xindent<Ceiling searches for the first element which is not less than Item. If
+such an element is found, a cursor that designates it is returned. Otherwise
+No_Element is returned.>
+
+@xcode<@b<function> First_Element (Container : Set) @b<return> Element_Type;>
+
+@xindent<Equivalent to Element (First (Container)).>
+
+@xcode<@b<function> Last (Container : Set) @b<return> Cursor;>
+
+@xindent<Returns a cursor that designates the last node in Container. If Container is
+empty, returns No_Element.>
+
+@xcode<@b<function> Last_Element (Container : Set) @b<return> Element_Type;>
+
+@xindent<Equivalent to Element (Last (Container)).>
+
+@xcode<@b<function> Previous (Position : Cursor) @b<return> Cursor;>
+
+@xindent<If Position equals No_Element, then Previous returns No_Element.
+Otherwise Previous returns a cursor designating the element that precedes the
+one designated by Position. If Position designates the first element, then
+Previous returns No_Element.>
+
+@xcode<@b<procedure> Previous (Position : @b<in out> Cursor);>
+
+@xindent<Equivalent to Position := Previous (Position).>
+
+@xcode<@b<function> "<" (Left, Right : Cursor) @b<return> Boolean;>
+
+@xindent<Equivalent to Element (Left) < Element (Right).>
+
+@xcode<@b<function> "@>" (Left, Right : Cursor) @b<return> Boolean;>
+
+@xindent<Equivalent to Element (Right) < Element (Left).>
+
+@xcode<@b<function> "<" (Left : Cursor; Right : Element_Type) @b<return> Boolean;>
+
+@xindent<Equivalent to Element (Left) < Right.>
+
+@xcode<@b<function> "@>" (Left : Cursor; Right : Element_Type) @b<return> Boolean;>
+
+@xindent<Equivalent to Right < Element (Left).>
+
+@xcode<@b<function> "<" (Left : Element_Type; Right : Cursor) @b<return> Boolean;>
+
+@xindent<Equivalent to Left < Element (Right).>
+
+@xcode<@b<function> "@>" (Left : Element_Type; Right : Cursor) @b<return> Boolean;>
+
+@xindent<Equivalent to Element (Right) < Left.>
+
+@xcode<@b<procedure> Reverse_Iterate
+   (Container : @b<in> Set;
+    Process   : @b<not null access procedure> (Position : @b<in> Cursor));>
+
+@xindent<Iterates over the elements in Container as per Iterate, with the
+difference that the elements are traversed in predecessor order, starting with
+the last node.>
+
+For any two elements @i<E1> and @i<E2>, the boolean values (@i<E1> < @i<E2>),
+(Key(@i<E1>) < @i<E2>), and (Key(@i<E2>) > @i<E1>) are all expected to be equal.
+If Key, Generic_Keys."<", or Generic_Keys.">" behave in some other manner, the
+behavior of this package is unspecified. Which subprograms of this package
+call Key, Generic_Keys."<" and Generic_Keys.">", and how many times the
+functions are called, is unspecified.
+
+In addition to the semantics described in A.18.7, the subprograms in package
+Generic_Keys named Floor, Ceiling, "<", and ">", are equivalent to the
+corresponding subprograms in the parent package, with the difference that the
+Key subprogram parameter is compared to elements in the container using the
+Generic_Keys generic formal relational operators.
+
+@i<@s8<Implementation Advice>>
+
+If @i<N> is the length of a set, then the worst-case time complexity of the
+Insert, Include, Replace, Delete, Exclude and Find operations that take an
+element parameter should be O((log @i<N>)**2) or better. The worst-case time
+complexity of the subprograms that take a cursor parameter should be O(1).
+
+!corrigendum A.18.10
+
+@dinsc
+
+The language-defined generic package Containers.Indefinite_Vectors provides a
+private type Vector and a set of operations. It provides the same
+operations as the package Vectors does, with the difference that the
+generic formal Element_Type is indefinite.
+
+@i<@s8<Static Semantics>>
+
+The declaration of the generic library package Containers.Indefinite_Vectors
+has the same contents as Containers.Vectors except:
+
+@xbullet<The generic formal Element_Type is indefinite.>
+
+@xbullet<The Element parameter of access subprogram Process of Update_Element
+may be constrained even if Element_Type is unconstrained.>
+
+!corrigendum A.18.11
+
+@dinsc
+
+The language-defined generic package Containers.Indefinite_Doubly_Linked_Lists
+provides private types List and Cursor, and a set of operations for each
+type. It provides the same operations as the package Doubly_Linked_Lists
+does, with the difference that the generic formal Element_Type is
+indefinite.
+
+@i<@s8<Static Semantics>>
+
+The declaration of the generic library package
+Containers.Indefinite_Doubly_Linked_Lists has the same contents as
+Containers.Doubly_Linked_Lists except:
+
+@xbullet<The generic formal Element_Type is indefinite.>
+
+@xbullet<The procedure with the profile:>
+@xcode<     @b<procedure> Insert (Container : @b<in out> List;
+                       Before    : @b<in>     Cursor;
+                       Position  :    @b<out> Cursor;
+                       Count     : @b<in>     Count_Type := 1);>
+@xindent<is omitted.>
+
+@xbullet<The Element parameter of access subprogram Process of Update_Element
+may be constrained even if Element_Type is unconstrained.>
+
+!corrigendum A.18.12
+
+@dinsc
+
+The language-defined generic package Containers.Indefinite_Hashed_Maps provides
+a map with the same operations as the package Hashed_Maps, with the
+difference that the generic formal types Key_Type and Element_Type are
+indefinite.
+
+@i<@s8<Static Semantics>>
+
+The declaration of the generic library package Containers.Indefinite_Hashed_Maps
+has the same contents as Containers.Hashed_Maps except:
+
+@xbullet<The generic formal Key_Type is indefinite.>
+
+@xbullet<The generic formal Element_Type is indefinite.>
+
+@xbullet<The procedure with the profile:>
+@xcode<     @b<procedure> Insert (Container : @b<in out> Map;
+                       Key       : @b<in>     Key_Type;
+                       Position  :    @b<out> Cursor;
+                       Inserted  :    @b<out> Boolean);>
+@xindent<is omitted.>
+
+@xbullet<The Element parameter of access subprogram Process of Update_Element
+may be constrained even if Element_Type is unconstrained.>
+
+!corrigendum A.18.13
+
+@dinsc
+
+The language-defined generic package Containers.Indefinite_Ordered_Maps
+provides a map with the same operations as the package Ordered, with the
+difference that the generic formal types Key_Type and Element_Type are
+indefinite.
+
+@i<@s8<Static Semantics>>
+
+The declaration of the generic library package
+Containers.Indefinite_Ordered_Maps has the same contents as
+Containers.Ordered_Maps except:
+
+@xbullet<The generic formal Key_Type is indefinite.>
+
+@xbullet<The generic formal Element_Type is indefinite.>
+
+@xbullet<The procedure with the profile:>
+@xcode<     @b<procedure> Insert (Container : @b<in out> Map;
+                       Key       : @b<in>     Key_Type;
+                       Position  :    @b<out> Cursor;
+                       Inserted  :    @b<out> Boolean);>
+@xindent<is omitted.>
+
+@xbullet<The Element parameter of access subprogram Process of Update_Element
+may be constrained even if Element_Type is unconstrained.>
+
+!corrigendum A.18.14
+
+@dinsc
+
+The language-defined generic package Containers.Indefinite_Hashed_Sets provides
+a set with the same operations as the package Hashed_Sets, with the
+difference that the generic formal type Element_Type is indefinite.
+
+@i<@s8<Static Semantics>>
+
+The declaration of the generic library package
+Containers.Indefinite_Hashed_Sets has the same contents as
+Containers.Hashed_Sets except:
+
+@xbullet<The generic formal Element_Type is indefinite.>
+
+@xbullet<The Element parameter of access subprogram Process of
+Update_Element_Preserving_Key may be constrained even if Element_Type is
+unconstrained.>
+
+!corrigendum A.18.15
+
+@dinsc
+
+The language-defined generic package Containers.Indefinite_Ordered_Sets
+provides a set with the same operations as the package Ordered_Sets, with the
+difference that the generic formal type Element_Type is indefinite.
+
+@i<@s8<Static Semantics>>
+
+The declaration of the generic library package
+Containers.Indefinite_Ordered_Sets has the same contents as
+Containers.Ordered_Sets except:
+
+@xbullet<The generic formal Element_Type is indefinite.>
+
+@xbullet<The Element parameter of access subprogram Process of
+Update_Element_Preserving_Key may be constrained even if Element_Type is
+unconstrained.>
+
+!corrigendum A.18.16
+
+@dinsc
+
+The language-defined generic procedures Containers.Generic_Array_Sort and
+Containers.Generic_Constrained_Array_Sort provide sorting on
+arbitrary array types.
+
+@i<@s8<Static Semantics>>
+
+The generic library procedure Containers.Generic_Array_Sort has the following
+declaration:
+
+@xcode<@b<generic>
+   @b<type> Index_Type @b<is> (<@>);
+   @b<type> Element_Type @b<is private>;
+   @b<type> Array_Type @b<is array> (Index_Type @b<range> <@>) @b<of> Element_Type;
+   @b<with function> "<" (Left, Right : Element_Type)
+      @b<return> Boolean @b<is> <@>;
+@b<procedure> Ada.Containers.Generic_Array_Sort (Container : @b<in out> Array_Type);
+@b<pragma> Pure (Ada.Containers.Generic_Array_Sort);>
+
+@xindent<Reorders the elements of Container such that the elements are
+sorted smallest first as determined by the generic formal "<" operator
+provided. Any exception raised during evaluation of "<" is propagated.>
+
+The generic library procedure Containers.Generic_Constrained_Array_Sort has the
+following declaration:
+
+@xcode<@b<generic>
+   @b<type> Index_Type @b<is> (<@>);
+   @b<type> Element_Type @b<is private>;
+   @b<type> Array_Type @b<is array> (Index_Type) @b<of> Element_Type;
+   @b<with function> "<" (Left, Right : Element_Type)
+      @b<return> Boolean @b<is> <@>;
+@b<procedure> Ada.Containers.Generic_Constrained_Array_Sort
+      (Container : @b<in out> Array_Type);
+@b<pragma> Pure (Ada.Containers.Generic_Constrained_Array_Sort);>
+
+@xindent<Reorders the elements of Container such that the elements are
+sorted smallest first as determined by the generic formal "<" operator
+provided. Any exception raised during evaluation of "<" is propagated.>
+
+@i<@s8<Implementation Advice>>
+
+The worst-case time complexity of a call on an instantiation of
+Containers.Generic_Array_Sort or Containers.Generic_Constrained_Array_Sort
+should be O(@i<N>**2) or better, and the average time complexity should be better
+than O(@i<N>**2), where @i<N> is the length of the Container parameter.
+
+Containers.Generic_Array_Sort and Containers.Generic_Constrained_Array_Sort
+should minimize copying of elements.
+
+
+!ACATS Test
+
+ACATS tests will be needed for this library.
+
+!appendix
+
+Report of the ARG Select Committee on Containers
+February 3, 2004
+
+
+Executive Summary
+
+The committee selected the second proposal as a starting point for a
+standard containers library, with a number of simple changes. The
+changes were simple enough that we produced a version of the library with
+the changes made (AI-00302-3/01).
+
+The resulting proposal is not much larger than the Vector and Matrix
+libraries already adopted for the standard. It also should be a good seed
+for a more encompassing secondary standard.
+
+Therefore, we recommend that the ARG adopt this alternative for the standard.
+
+     By the ARG Select Committee on Containers:
+
+           Randy Brukardt
+           Bob Duff
+           Tucker Taft
+
+Full Report
+
+Goals
+
+A core library of containers is an important addition to Ada. Other competitive
+programming languages include standard sets of containers, and these are
+widely used. Users often note that a standard set of containers is a missing
+piece of Ada. In addition, adding such containers to the standard is not
+a large burden on implementers.
+
+However, the resources available for work on the standard preclude adding a
+large container library to the standard. If the library is too large, it will
+be insufficiently reviewed, and that has the danger of providing something
+useless.
+
+Therefore, the committee settled on a limited set of goals:
+   (1) To provide a number of the most useful containers to Ada users in
+       a standard fashion;
+   (2) To provide a framework for future work in this area (hopefully leading
+       to a secondary or de-facto standard).
+
+We considered other goals as well. Performance issues were deemed of secondary
+importance. Most uses of containers (indeed, most software) do not have
+critical performance requirements. To provide a library with the variety of
+components needed to meet critical requirements (bounded and unbounded forms,
+array and list implementations, etc.) would be beyond the resources available
+to work on the standard. Moreover, the existence of many components actually
+makes construction of simple applications harder: the programmer has to choose
+a component based on performance considerations that are simply irrelevant for
+the application.
+
+Evaluation of existing proposals
+
+We determined that the most important containers are the following:
+    * extensible "vectors" (like an array, indexed by any discrete type);
+    * (hashed) "maps" (or "hash table", with arbitrary keys);
+    * (sorted) "sets" (set of arbitrary items).
+The names "map", "set", and "vector" are those used in the Java containers.
+
+We evaluated the two proposals for their support of these components.
+
+Alternative 1 (AI-302-1/07) contains a number of low level data structure
+components such as Lists, Bags, Queues, etc. These can be used to create
+"vector", "map", and "set" containers, but the containers themselves are
+absent. Moreover, most of these components are relatively easy to create
+when needed.
+
+Alternative 2 (AI-302-2/02) contains mainly five containers: vector, list,
+map, set, and multiset. These include the abstractions mentioned above. We
+also determined that the basic design was consistent and sound.
+
+Therefore, we discarded alternative 1, and concentrated on improving and
+simplifying alternative 2.
+
+We decided the sorts of changes that we would consider. The great value to
+having containers in the standard is that they are standard: everybody has
+them and can use them. Perfection is not required of the standard components.
+Moreover, what is one person's "improvement" is another's "mistake". In
+addition, we run the risk of introducing real errors by further fiddling.
+
+Therefore, we decided to simplify the interfaces by deleting unnecessary
+capabilities, by systematic substitutions, and by introducing missing
+capabilities (along with general wordsmithing). In particular, we avoided
+changing existing interfaces unless there was a clear error.
+
+The specific improvements and simplifications are detailed in the Appendix.
+
+Performance issues
+
+For the purposes of components in the standard, the precise performance of them
+is not important. Whatever the performance is will be good enough for the vast
+majority of uses - in prototyping, quick and dirty programs, and the majority
+of programs that aren't performance critical. Therefore, we provide only a
+single version of each component. We don't, for instance, provide both Vectors
+and Lists, which are really the same abstraction with the different performance
+characteristics.
+
+However, it is important that the performance characteristics of the components
+be specified. That is, if searches are expected to be no worse than O(N), we
+need to say that. That's because we want programs using the components to be
+portable. That wouldn't be true for programs using components with large
+numbers of items if the performance characteristics vary widely between
+implementations. Consider a Vector component. It could in theory be implemented
+with an array or with a linked list. The cost of an arbitrary insertion is O(N)
+for the array implementation and O(1) for the list implementation. If a program
+using a large vector is moved from a list implementation to an array
+implementation, the performance change could be so large as to make the program
+non-functional. That is unacceptable, so we specify minimum performance
+characteristics. But those characteristics are not intended to specify a
+particular implementation, only to insure that some characteristics can be
+relied upon.
+
+Therefore, the containers library needs to suggest some performance
+characteristics. We believe Implementation Advice is best for this purpose,
+as we don't have to be as precise in the language defining the characteristics,
+and implementations are required to document deviations from the given
+advice.
+
+Appendix
+
+Detailed changes made to the Alternative 2 proposal
+
+The Unchecked_Modification packages were dropped. These are just a hack to
+avoid copying keys - a solely performance-based concern. Other stuff does
+not logically belong in keys, and modifying the key value itself it a disaster
+waiting to happen.
+
+The Vector, List, and Multiset abstractions are essentially the same
+abstraction with differences in performance and details. When performance
+is not critical, only one is needed.
+
+The package structure has many levels of empty packages for organization.
+These are unnecessary when there are only a few packages. Moreover, related
+packages can be given similar names (i.e. "Bounded_Set", "Protected_Vector"),
+which provides all of the organization needed. The extra empty packages
+were eliminated. Similarly, "Unbounded" was dropped; these are the most
+general forms, and should be the ones used for general-purpose programming.
+Other forms (in a secondary standard) would be more specialized.
+
+We discussed dropping the special string maps. We eventually decided to keep
+them, because string maps are common, and a Map cannot be instantiated with
+"String" (the key type must be definite).
+
+We also discussed whether Sets should be sorted. We concluded that the extra
+cost of sorted insertions is fairly small, and thus there is little advantage
+to using unsorted sets other than when performance is critical (which again
+is not the purpose of the standard). We did, however, name the package
+"Sorted_Sets" so that a basic unsorted set could be provided in a secondary
+standard without contorted naming.
+
+We added a modular Hash_Type to Ada.Containers. The choice of Integer'Base is
+a horrible one on compilers that use 16-bit Integer (as allowed by the
+standard), and in any case, the hashing type should be modular.
+
+The string hash and comparison functions were moved to be part of the
+Ada.Strings hierarchy. It would be a bad idea to have the hash functions
+of all types gathered in one place (in the containers library).
+
+Unbounded string hash and comparison functions were added.
+
+We changed the type names to the more descriptive "Vector_Type", "Map_Type",
+and "Set_Type". These are much better for users who use Use clauses. The
+argument that having a common name makes it easier to change between containers
+is mostly irrelevant: changing between the provided containers is going to be
+rare. Moreover, qualifying "Container_Type" (that is, "Vector.Container_Type")
+would be necessary in any unit with more than one container -- eliminating any
+advantage for using the same name.
+
+The proposal confused the meaning of "iterator", using it both for the
+code that visits each element of a container (the conventional meaning) and
+the "handle" or "cursor" used to access an element of a container. We decided
+to use "cursor" for the second meaning to make the interfaces clearer.
+
+We added a sort routine to Vector. For some reason, this was only present
+in the (removed) List abstraction. Having a simple sort available can
+simplify many programming problems.
+
+We added legality rules that these packages must be instantiated at the
+library level. The requirement that these packages do not
+leak memory (like Ada.Strings.Unbounded) imply that they are implemented with
+controlled types (or something like controlled types). We do not want to
+implicitly require implementers to support nested controlled types without
+making that support available to users. (If AI-344 or AC-50 were adopted, we
+could drop these rules.)
+
+The proposal was completely missing definitions for the string hash and
+compare functions.
+
+Performance requirements were moved from the !proposal into Implementation
+Advice. As much as possible, mention of specific implementation strategies
+was moved into AARM notes following that Advice. (We're not going to specify
+red-black trees!).
+
+An Assert pragma was added to the Vector package to prevent instantiation with
+a type for which Index_Type'Base'First = Index_Type'First. For such a type,
+the initial value of Last and the value of Front must necessarily raise
+Constraint_Error. It's better to fail an assertion immediately, rather than
+during some later operation.
+
+The Map container in the proposal is far too specific to a particular
+implementation. It exposes that implementation in the interface, and as a
+result makes iteration operations harder. That seems like a bad choice for
+a simple abstraction; it's fine to suggest an implementation, but bad to
+make it part of the interface. We therefore simplified the interface and the
+description. (We consulted with the author of the proposal on this and other
+changes.)
+
+****************************************************************
+
+From: Marius Amado Alves
+Sent: Wednesday, February 4, 2004  5:13 AM
+
+>Report of the ARG Select Committee on Containers
+>February 3, 2004
+>...
+
+Sorry for my poor knowledge of ARG procedure.
+Does this step mean the library is secured for Ada 2005?
+Thanks.
+
+****************************************************************
+
+From: Martin Dowie
+Sent: Wednesday, February 4, 2004  5:30 AM
+
+> Sorry for my poor knowledge of ARG procedure.
+> Does this step mean the library is secured for Ada 2005?
+> Thanks.
+
+Nope - it's still a "Work Item", see:
+
+http://www.ada-auth.org/cgi-bin/cvsweb.cgi/AIs/AI-20302.TXT?rev=1.1
+
+
+
+Also, in the text of the AI :-
+
+with Ada.Containers;
+package Ada.Strings.Case_Insensitive is
+    pragma Pure (Case_Insensitive);
+
+    function "=" (Left, Right : String) return Boolean;
+    function "/=" (Left, Right : String) return Boolean;
+             ^^^^
+Guess this wasn't really meant.
+
+****************************************************************
+
+From: Martin Dowie
+Sent: Wednesday, February 4, 2004  8:11 AM
+
+1) Couple of typos in package Ada.Containers.Maps
+
+     generic
+        with procedure Process (Cursor : in Cursor_Type) is <>;
+     procedure Generic_Iteration (Map : in Map_Type);
+
+     - description refers to 'Generic_Cursor'
+
+     function Length (Map : Map_Type) return Natural;
+
+     - description refers to 'Container' when it should be 'Map'
+
+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?
+
+****************************************************************
+
+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.
 
-A comment on type names.
+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.
 
-Ada 83, with the unfortunate* exception of File_Type, did not use
-"_Type" on the end of predefined type names. We have Address and Count,
-not Address_Type and Count_Type. Ada 95 adhered to this principle, so we
-have Storage_Element and Unbounded_String, not Storage_Element_Type and
-Unbounded_String_Type.
-
-For consistency, I think the Ada-0X process should also adhere to this
-principle. The use of "_Type" on type names in the proposal should be
-eliminated. This takes some time and thought to do well; I am willing to
-volunteer for the effort if the Committee cannot spare the time and
-cannot find anyone preferable.
-
-This is a matter of consistently. While it is not my style, and not
-recommended by the Quality and Style Guide, I have used libraries that
-use the "_Type" convention without problem. I am concerned that the ARM
-be consistent far more than I am about what convention the ARM uses.
+****************************************************************
 
-*"Unfortunate" because it is inconsistent.
+From: Randy Brukardt
+Sent: Thursday, February 5, 2004  3:23 PM
 
-****************************************************************
+Jeff Carter wrote:
 
-From: Matthew Heaney
-Sent: Friday, February 6, 2004  9:33 AM
+> The normative text for vectors says
+>
+> "A vector container object manages an unconstrained internal array"
+>
+> That specifies an array implementation.
 
-I have updated the reference implementation, which now has the sorted
-set container, too.
+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.
 
-There's also a test_sets.adb, so you have something to run.  You can
-pass a seed on the command line.
+...
+> 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.
 
-<http://home.earthlink.net/~matthewjheaney/charles/ai302-20040206.zip>
+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.
 
-I'll take care of the hashed map containers this weekend, and post Mon AM.
+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: Friday, February 6, 2004  3:36 PM
-
-Martin Dowie wrote:
-
-> I was thinking, primarily, of a project that used single (bounded) lists to
-> hold commands (a basic, domain-specific, scripting language I guess),
-> one of which was 'stop this sequence of commands'.
-
-It sounds like you have a sequence container, that you traverse from
-front to back.
-
-The only sequence container in the proposal is a vector, which doesn't
-have a passive iterator.  Again, I recommend just using a loop:
-
-    for Index in First (V) .. Last (V) loop
-       declare
-          Command : Command_Type := Element (V, Index);
-       begin
-          exit when Is_Stop (Command);
-          -- process command
-       end;
-    end loop;
-
-
-If these are commands that have an order (say, each command has a
-timestamp, and commands are executed in timestamp order), then you can
-use the sorted set.  Again, an explicit loop is appropriate:
-
-declare
-    I : Cursor_Type := First (S);
-    J : constant Cursor_Type := Back (S);
-begin
-    while I /= J loop
-       declare
-          Command : Command_Type := Element (I);
-       begin
-          exit when Is_Stop (Command);
-          -- process command
-       end;
-
-       Increment (I);
-    end loop;
-end;
+Sent: Thursday, February 5, 2004  3:40 PM
 
-****************************************************************
+Randy Brukardt wrote:
 
-From: Alexandre E. Kopilovitch
-Sent: Friday, February 6, 2004  4:24 PM
+> Precisely my point. That is intended to say that there is a logical array in
+> the container, but not necessarly an actual one.
 
-> The only sequence container in the proposal is a vector,
+Yes, exactly.  This allows the implementor to leave the type system in
+order choose the optimal implementation for the vector container.
 
-Ah, yes, it's Sequence - quite right name for that container (and not Vector).
+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: Friday, February 6, 2004  7:17 PM
+Sent: Thursday, February 5, 2004  6:52 PM
 
 Randy Brukardt wrote:
 
-> Let's see:
-> - direct analogs to indexing, both LHS and RHS (Element, Replace_Element);
-> - slices (nope);
-> - 'First (First), 'Last (Last), 'Length (Length);
+>>The normative text for vectors says
+>>
+>>"A vector container object manages an unconstrained internal array"
+>>
+>>That specifies an array implementation.
 >
-> Looks like pretty much everything is in there. And slicing will be expensive
-> if the implementation is not a straight array, so it's somewhat dubious.
-> Insert and Delete provide easier ways of adding or removing items than
-> slices - and how often do you use a slice of a non-string type for something
-> other than inserting or deleting elements anyway??
-
-Slicing isn't included because C++ doesn't have slices, so it's a
-foreign concept to its library and users. If we want to attract users of
-inferior languages to Ada, it should be because Ada is better. Ada's
-slices are a way that Ada is better; Ada's standard extensible array
-component should be better than its competition by also offering them. I
-do not see mimicking C++'s shortcomings as advisable.
-
-Insertion and deletion are basic operations of lists, but not of arrays.
-That's why the list and vector components had the same set of
-operations: they both specify lists with different implementations.
-
-Since String is an array, and [Un]Bounded_String is an extensible array,
-and we're now told the correct name is Vector, shouldn't these be
-renamed to something like Character_Vector?
-
-> Ada doesn't (and isn't) going to support user-defined indexing or
-> user-defined attributes, so this is about the best you can do. So what's the
-> complaint (other than the name)??
-
-I don't expect user-defined indexing, slices, or attributes, which is
-why I talked about "analogs" to them. Missing slices is one complaint.
-And, yes, the name is unarguably wrong.
-
-In the C family of languages, users are accustomed to having to look at
-implementations in order to understand how to use something. Subprogram
-"prototypes" (yet another misused term to add to the collection) are
-generally insufficient, and appropriate comments are often lacking. So
-it comes as no surprise to me that C++ expects newcomers to its library,
-looking for an extensible array, and not finding anothing with an
-appropriate name, to have to look at the operations of the components to
-find that the inappropriately named "vector" is really an extensible array.
-
-However, this is not the Ada way, and I think it completely
-inappropriate to mimick this mistake. Looking at other languages'
-library to select useful components is fine; insisting that an Ada
-version must be identical to that of another language, including
-mistakes, is not.
-
-> The user can easily code a queue in terms of a Vector (that's one of the
-> uses of Insert!). We dropped the list component because it had an identical
-> interface to the Vector component, but was less flexible (no computed O(1)
-> access).
-
-The perfomance of a queue based on an extensible array is likely to be
-just as objectionable as extracting an element from an extensible array
-based on a list. That the vector and list components both had the same
-interface is further evidence that mimicking the STL is a bad idea.
-Insert and delete are as foreign to an extensible array as indexing and
-slicing should be to a list.
-
-> In my view, it is a mistake for projects to depend on standard containers
-> where there are critical performance requirements (not just time, but also
-> space as well). In that case, you really have to have control of the
-> implementation -- you really need *all* of the source code. You can't trust
-> something provided by the standard (or your compiler vendor) in those cases.
-
-I agree. That doesn't mean that the standard shouldn't provide a basis
-for queues with performance characteristics suitable for performance
-non-critical applications, which an extensible array does not provide.
+> 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.
 
-From: Randy Brukardt
-Sent: Friday, February 6, 2004  8:24 PM
+> 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.
 
-Jeff Carter wrote:
+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 agree. That doesn't mean that the standard shouldn't provide a basis
-> for queues with performance characteristics suitable for performance
-> non-critical applications, which an extensible array does not provide.
-
-Huh? You've said, in effect, that the performance isn't good enough for
-applications where the performance doesn't matter. That's a pretty goofy
-statement!
-
-My opinion has not changed: if you care about performance *at all*, you
-*cannot* depend on *any* standard containers. But usually the performance
-does not matter at all (or so little as to be equivalent to not at all): the
-number of elements in the container is small (which would be true for
-virtually all queues), and/or it is used infrequently, and/or the
-application is a throw-away.
-
-Otherwise, if you are writing portable code, you shouldn't use a predefined
-container library at all -- the performance is likely to vary much more
-across implementations than code you write yourself. For instance, on
-Janus/Ada, any generic list container is going run 2-5 times slower than the
-same list created yourself -- that's just the effect of the extra call
-overhead and the shared body (which means the elements will be dynamically
-allocated - separately - in any case - at least doubling the allocation
-overhead). I'd expeect that effect to be much less on GNAT, for example,
-because they don't share generic bodies and thus don't have the double
-allocation overhead.
-
-If your application doesn't care about the component being 5 times slower,
-then it is highly unlikely that it is going to care about whether the
-Vector/Sequence/List component is implemented as an array, as a list, as a
-tree, as a hash table, or as something else.
-
-My preference with these components would be to say absolutely nothing about
-performance or implementation (because anything said is as meaningless as
-real-time metrics are). But others believe that that would cause real
-portability problems, and I'm willing to go along with that.
-
-The problem I see is a lot of people are looking far too closely at tiny
-pieces of abstractions.  You might have a queue or a list as part of a large
-abstraction, but they're pretty much useless by themselves. And given that
-creating a queue or stack (both of which have only two operations, both
-trivial!) would take 3 minutes max, it makes no sense to use a complex (and
-necessarily slow) container library for just that -- indeed, it probably
-would be more work to use a container than the 3 minutes.
-
-I much prefer the vision of this containers library, where the only
-containers included are those that are large, complex, multi-purpose, and
-have a clear abstraction.
+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: Friday, February 6, 2004  7:39 PM
-
-Matthew Heaney wrote:
-
-> No.  Vector iterators are fragile, and hence very error prone.
+Sent: Thursday, February 5, 2004  11:38 AM
 
-Modifying a structure from an iterator should be a bounded error.
+Tucker Taft wrote:
 
-> They are fragile because the (logical) internal array gets thrown away
-> during expansion, which invalidates the iterator.  It's too hard to keep
-> track of whether a vector iterator is still valid, and most of the time
-> you end up with a dangling reference.
+> 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.
 
-You can only talk about what happens internally during an operation if a
-specific implementation is required, which Randy assures us is not the case.
+I disagree, even though I know that's dangerous when discussing Ada with
+STT. An application that uses both extensible arrays and mathematical
+vectors will be very confusing if both are called vectors. Since an
+explicit design goal of Ada is to emphasize ease of reading, calling an
+extensible array a vector seems inappropriate.
 
-> A "set" is really any sorted sequence of items.  If you want set
-> intersection, symmetric difference, etc, then just use a generic
-> algorithm.  See the Charles library for such algorithms.
+> 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).
 
-I've used sets for decades, in discrete math, in specification languages
-such as Z, and in programming. A set is an unordered collection of
-elements from a universe that provides operations such as membership,
-union, intersection, and the like, represented by mathematical symbols
-that I can't reliably represent in an e-mail.
+I have no objections to an extensible array, provided it's clearly
+identified as such. I think it should look different from the proposal,
+but that's mainly a taste issue. I'd want direct analogs to indexing,
+both LHS and RHS (Put and Get?); slices, both LHS and RHS (Replace_Slice
+and Slice?); and 'First, 'Last, and 'Length (though 'First is a constant
+for an EA). An equivalent to 'range would be nice, but impossible. The
+only difference to a normal array would be that Put and Replace_Slice
+can accept indices not in First .. Last. I haven't given it a great deal
+of thought, so I'm sure I'm missing some subtleties, but I don't see a
+need for Front, Back, Insert, Delete, and so on.
 
-An implementation of a set may be sorted to speed up operations, but
-that's a feature of the implementation, not of the concept implemented.
-That's a distinction that many users of C-family languages seem unable
-to make, but that I expect from those who embrace Ada.
+The proposal says that containers "that are relatively easy to code,
+redundant, or rarely used are omitted". It also says that lists are
+difficult to implement correctly. Given a list, structures such as
+deques, stacks, and especially queues are easy to implement. Since
+queues are common structures and not redundant (none of the proposed
+containers provides an efficient implementation of a queue), the
+proposal itself seems to argue that lists should be provided, since they
+are not easy to code correctly, and provide a basis for the user to
+easily code queues.
 
-> The name for Delete_Sans_Increment comes from Emacs lisp, which has the
-> functions file-name-sans-extension and file-name-sans-versions.
+> 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.
 
-Yet another case of mimicking others' errors.
+There was an article by Mills [Harlan D. Mills, Richard C. Linger: Data
+Structured Programming: Program Design without Arrays and Pointers. IEEE
+Trans. Software Eng. 12(2): 192-197 (1986)] that proposed that
+applications only use queues, stacks, and sets (real sets, with union,
+intersection, and such operations). It's an interesting concept, and I
+agree with the aim of programs using appropriate abstractions and hiding
+lower level implementation details, especially use of pointers.
 
-> It was also in homage to Ada's French history, given that her original
-> designer was French, and worked for a French company.
->
-> Why do you think "rendevous" was named that way?
+****************************************************************
 
-"Rendezvous" is not a predefined indentifier in the ARM. It was chosen
-because no English word has the precise meaning intended, and Ada's
-designers understood the importance of precise terminology.
-
-> If you don't immediately grok how vectors and sets and maps work, then I
-> suggest familiarizing yourself with the STL. There are lots of tutorials
-> on the WWW.
-
-I've been using arrays, including extensible arrays, sets, and maps for
-decades. I've also been using vectors for decades, having done a lot of
-scientific programming that required matrix math. I doubt that a study
-of C++ mistakes would have any effect besides raising my blood pressure.
+From: Alexandre E. Kopilovitch
+Sent: Thursday, February 5, 2004  9:04 AM
 
-****************************************************************
+Tucker Taft wrote:
 
-From: Jeffrey Carter
-Sent: Friday, February 6, 2004  7:22 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.
 
-Randy Brukardt wrote:
+So call it Java_Vector - that will be at least consistent.
 
-> 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.
+Do you think that Java meaning for "vector" is more significant for Ada than
+mathematical meaning of this term (which never implied extensibility) ?
 
-On closer inspection, the Size and Resize operations certainly imply an
-array implementation; they are meaningless otherwise.
+Why not call that thing Flexible_Array (after Algol-68, I think) - this name
+will directly reflect the essense.
 
 ****************************************************************
 
-From: Randy Brukardt
-Sent: Friday, February 6, 2004  9:09 PM
+From: Robert A. Duff
+Sent: Thursday, February 5, 2004  1:37 PM
+
+Bill Wulf and other professors at CMU circa late 1970's were using the
+term "vector" to mean "array" (not necessarily extensible); that's the
+first time *I* heard it.  So it's not a Java-ism.
 
-Huh? Resize tells the container a reasonable size to use; what the container
-does with that information is up to it. Size simply returns that
-information.
-
-That's no different than many of the attributes in Ada, which (if set),
-always return the values that they were set to. But what the compiler does
-with those values is (almost) completely implementation-defined.
-
-The only real requirement here is O(1) element access (which prevents the
-use of a straight linked list).
-
-Janus/Ada will probably use an array of pointers (or possibly array of
-arrays of pointers); we're going to be (implicitly) allocating the elements
-anyway, we might as well do it explicitly and take advantage of that to make
-Insert/Delete/Sort (and any expansions) much cheaper (presuming the elements
-are bigger than scalar types). An array of arrays of pointers is even
-better, because insertion cost is bounded by the maximum size of an array
-chunk -- but there is more overhead and complexity, so I'd like to see some
-real uses before deciding on an implementation.
-
-Note that a pure list component has no real opportunity for "better"
-implementations, and indeed, any implementation on Janus/Ada would suffer
-from "double" allocation.
+I think this meaning of "vector" derives from the maths meaning,
+even if it's not precisely the same thing.
 
 ****************************************************************
 
-From: Martin Dowie
-Sent: Saturday, February 7, 2004  4:02 AM
+From: Stephen Leake
+Sent: Thursday, February 5, 2004  2:18 PM
+
+Jeffrey Carter <jrcarter@acm.org> writes:
 
-> We dropped the passive iterator from the Ada.Directories package precisely
-> because even ARG members were confused about how it worked. Even though it
-> was a classic passive iterator with a Quit parameter. Perhaps the confusion
-> really was the Quit parameter (I thought it was the whole idea), but in any
-> case, you've got to keep them simple.
-
-I didn't find it confusing so I provided an extra child
-Ada.Directories.Iterate - and I've used it repeatedly!
-
-> > This pattern has since shown itself to be quite common in embedded
-> > systems - for either domain-specific scripting languages or graphics.
-> >
-> > There is the other idiom where one is processing an iteration of items
-> > and an external event occurs that stops the processing - e.g. the 'stop'
-> > button is pushed on a GUI-search window, but it could equally be a
-> > 50Hz message over a 1553.
+> Tucker Taft wrote:
+>
+> > 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.
 >
-> It seems to me that an abort situation is best handled by propagating an
-> exception. Otherwise, you end up distributing termination code/flags
-> everywhere in the application. But YMMV.
+> I disagree, even though I know that's dangerous when discussing Ada
+> with STT. An application that uses both extensible arrays and
+> mathematical vectors will be very confusing if both are called
+> vectors. Since an explicit design goal of Ada is to emphasize ease of
+> reading, calling an extensible array a vector seems inappropriate.
 
-I have tended to work in deeply enbedded systems, where exceptions (in
-any language!) are at best frowned upon and quite often forbidden! :-(
+I agree with Tucker. I have code that uses both Cartesian vectors and
+extensible arrays. One is SAL.Math_Double.DOF_3.Cart_Vector_Type, the
+other is SAL.Poly.Unbounded_Arrays. Obviously, I have different names
+for them, as Carter wants. But if I called them
+SAL.Math_Double.DOF_3.Vector and SAL.Poly.Vector, I would have no
+chance of confusion. That's what package hierarchies are for.
 
-****************************************************************
+Since both Java and C++ use the term "vector" for an extensible array,
+I think Ada should also. Part of the point of the OY revision is to
+make the language more attractive to current users of other languages.
+This is an easy way to do that.
 
-From: Martin Dowie
-Sent: Saturday, February 7, 2004  4:25 AM
+> (Replace_Slice and Slice?); and 'First, 'Last, and 'Length (though
+> 'First is a constant for an EA).
 
-> > I was thinking, primarily, of a project that used single (bounded) lists to
-> > hold commands (a basic, domain-specific, scripting language I guess),
-> > one of which was 'stop this sequence of commands'.
->
-> It sounds like you have a sequence container, that you traverse from
-> front to back.
+'First is not constant for SAL.Poly.Unbounded_Arrays; I provide both
+Append and Prepend operations. I don't think I've ever used Prepend,
+though; it was really just an exercise in what was possible.
 
-Pretty much, although we also read in where each 'First' is as the whole
-contained many 'subroutines'.
+> .. I don't see
+> a need for Front, Back, Insert, Delete, and so on.
+
+I use Insert and Delete in real applications.
+
+> The proposal says that containers "that are relatively easy to code,
+> redundant, or rarely used are omitted". It also says that lists are
+> difficult to implement correctly. Given a list, structures such as
+> deques, stacks, and especially queues are easy to implement. Since
+> queues are common structures and not redundant (none of the proposed
+> containers provides an efficient implementation of a queue), the
+> proposal itself seems to argue that lists should be provided, since
+> they are not easy to code correctly, and provide a basis for the
+> user to easily code queues.
 
+I agree. A lists package would be nice.
 
-> The only sequence container in the proposal is a vector, which doesn't
-> have a passive iterator.  Again, I recommend just using a loop:
+But I also agree with Tucker, that it is difficult to come up with one
+list package that really meets a wide range of needs.
 
-I suspect the first thing I will do is add an extra child generic subprogram
-Ada.Containers.Vectors.Iterate! :-)
+Perhaps one list package, that meets a narrow range of needs, would
+still be useful. It would set a style standard for other list packages.
 
 ****************************************************************
 
-From: Martin Krischik
-Sent: Saturday, February 7, 2004  6:16 AM
+From: Matthew Heaney
+Sent: Thursday, February 5, 2004  2:48 PM
 
-> I suspect the first thing I will do is add an extra child generic
-> subprogram Ada.Containers.Vectors.Iterate! :-)
+Alexandre E. Kopilovitch wrote:
 
-Well, guess don't use GNAT. GNAT gets quite upset if you try to add something
-to the Ada packages.
+> So call it Java_Vector - that will be at least consistent.
+>
+> Do you think that Java meaning for "vector" is more significant for Ada than
+> mathematical meaning of this term (which never implied extensibility) ?
+>
+> Why not call that thing Flexible_Array (after Algol-68, I think) - this name
+> will directly reflect the essense.
 
-****************************************************************
+Tucker T. and Bob D. are both correct: the container is a "vector."
 
-From: Marius Amado Alves
-Sent: Saturday, February 7, 2004  7:45 PM
+Alexandre K. and Jeff C. are both incorrect.  The container is not a
+list, not a Java_Vector, not an Extensible_Array, and not a Flexible_Array.
 
-I'd expect *any* compiler to get really upset with this ;-)
+It is a vector.  It has the same semantics as the identically-named
+container in the STL.  The one named "vector."
 
-****************************************************************
+The container whose name is vector does not have array semantics.  There
+is no slicing for example.
 
-From: Martin Dowie
-Sent: Sunday, February 8, 2004  2:08 AM
+The container whose name is vector has the following important properties:
 
-"gcc -gnatg" or "gnatmake -a" will stop any warnings :-)
+o inserting at the back end is amortized constant time
+o supports random access of elements, in constant time
 
-****************************************************************
+Yes, internally a vector is implemented as an array.  The Size function
+returns the length of this internal array, and Resize can be used to
+expand its length.
 
-From: Martin Krischik
-Sent: Saturday, February 7, 2004  5:09 AM
+But it is not an array.  It is a container.  Whose name is "vector".
+Just like the one in the STL.
 
-> Jeffrey Carter wrote:
+****************************************************************
 
-> > Given a list, structures such as
-> > deques, stacks, and especially queues are easy to implement. Since
-> > queues are common structures and not redundant (none of the proposed
-> > containers provides an efficient implementation of a queue), the
-> > proposal itself seems to argue that lists should be provided, since they
-> > are not easy to code correctly, and provide a basis for the user to
-> > easily code queues.
-
-> The user can easily code a queue in terms of a Vector (that's one of the
-> uses of Insert!). We dropped the list component because it had an identical
-> interface to the Vector component, but was less flexible (no computed O(1)
-> access).
-
-True enough. But if you wanted a build generic queue on top of the vector the
-tag should not be hidden from view. Otherwise one need to repeat all the
-access methods instead of just renaming the one provided from the parent
-package.
+From: Alexandre E. Kopilovitch
+Sent: Thursday, February 5, 2004  3:46 PM
 
-In fact the hidden tag is the one feature which I realey dislike in charles.
+No problem with all that if another term was chosen. Now, with "vector", this
+is name squatting (well, participation in name squatting in Ada case), which
+is fully appropriate for Java, somehow understandable for C++, but seems
+(still) inappropriate for Ada, especially taking into account that the involved
+term belongs to some Ada-friendly domain.
 
 ****************************************************************
-
-From: Stephen Leake
-Sent: Saturday, February 7, 2004  8:40 AM
-
-"Randy Brukardt" <randy@rrsoftware.com> writes:
 
-> Report of the ARG Select Committee on Containers
-> February 3, 2004
-
-Thanks for the committee's hard work on this.
+From: Robert A. Duff
+Sent: Thursday, February 5, 2004  3:38 PM
 
-What is the rationale for making the Map Key_Type definite, as opposed
-to indefinite? Since an indefinite Key_Type is required for
-Containers.Maps.Strings, why not make that capability available to the
-users?
+I wrote:
 
-I don't see a discussion of this in AI-302-03/01.
+> Bill Wulf and other professors at CMU circa late 1970's were using the
+> term "vector" to mean "array" (not necessarily extensible); that's the
+> first time *I* heard it.  So it's not a Java-ism.
 
+Actually, the meaning was "one-dimensional array".  But there was no
+implication that they could grow.
 
-Another point: Containers.Vectors.Size should return Index_Type'Base,
-and the Size parameter in Resize should also be Index_Type'Base. It's
-confusing to have different types for Size and Index.
+> I think this meaning of "vector" derives from the maths meaning,
+> even if it's not precisely the same thing.
 
-There's also a problem if Natural'Last < Index_Type'Last; you
-can't have a vector that contains every index!
+I mean, what's a vector in 3-space?  Basically, a one-dimensional array
+of 3 real numbers -- the X, Y, and Z coordinates.
 
-****************************************************************
+Matt wrote:
 
-From: Randy Brukardt
-Sent: Saturday, February 7, 2004  6:03 PM
+> It is a vector.  It has the same semantics as the identically-named
+> container in the STL.  The one named "vector."
 
-> What is the rationale for making the Map Key_Type definite, as opposed
-> to indefinite?
+This stuff comes from the C++ STL.  I think gratuitous differences from
+that are unhelpful.  (But I admit that I was one of the folks pushing
+for "cursor" instead of "iterator".)
 
-The 'committee' primarily adopted the existing proposal submitted by Matt
-Heaney. We decided not to change any of the major design decisions of that
-proposal - because no package will suit everyone or every need, and we felt
-it was more important to standardize something coherently designed for most
-needs than to fiddle endlessly with it and risk introducing serious bugs.
-
-Which is to say, I don't know. :-)
-
-> Since an indefinite Key_Type is required for
-> Containers.Maps.Strings, why not make that capability available to the
-> users?
-
-We definitely expect that the strings container will use a purpose-built
-data structure for storing strings, not some general indefinite item
-capability. Ways to compactly and efficiently store sets of varying size
-strings are well known and commonly used.
+> The container whose name is vector does not have array semantics.  There
+> is no slicing for example.
 
-Such algorithms could be extended to a general "unconstrained array of
-elementary", but that hardly seems to be a worthwhile definition for keys.
+Well, "no slicing" is hardly fundamental.  It could be added, or
+programmed by the client.
 
-...
-> Another point: Containers.Vectors.Size should return Index_Type'Base,
-> and the Size parameter in Resize should also be Index_Type'Base. It's
-> confusing to have different types for Size and Index.
+> The container whose name is vector has the following important properties:
 >
-> There's also a problem if Natural'Last < Index_Type'Last; you
-> can't have a vector that contains every index!
+> o inserting at the back end is amortized constant time
+> o supports random access of elements, in constant time
 
-Yes, that's a serious problem on Janus/Ada (Integer is 16-bit). However, you
-want the Size and Resize operations to take a numeric type that contains
-zero -- and certainly Index_Type is not that. Index_Type could be a subtype
-of an enumeration type or a subtype of a modular type (neither of which can
-contain zero) or a subtype of an integer type not containing zero.
-
-We had a short, inconclusive discussion about whether the index type ought
-to be range <> rather than (<>) (because enumeration and modular types fail
-the assertion and thus aren't directly usable), but that still doesn't
-guarantee a zero. Moreover, if the integer type has negative numbers, then
-the Length of the vector could be larger than Index_Type'Last.
-
-So I don't see a great solution. I wondered about using "Hash_Type" here (it
-has the correct properties), but that seems like a misuse of the type (and a
-bad idea in a library that most Ada programmers will read - you want to show
-them good style in standard libraries).
+I think "random access" is the essence of array semantics.  After all,
+anything you can do with an array you can do with a linked list, and
+vice versa -- the only fundamental difference is the efficiency
+properties.
 
 ****************************************************************
-
-From: Martin Krischik
-Sent: Saturday, February 7, 2004  5:15 AM
 
-> The perfomance of a queue based on an extensible array is likely to be
-> just as objectionable as extracting an element from an extensible array
-> based on a list. That the vector and list components both had the same
-> interface is further evidence that mimicking the STL is a bad idea.
-> Insert and delete are as foreign to an extensible array as indexing and
-> slicing should be to a list.
-
-Well, depends. Most queues are not supposed to grow indefinetly so an using a
-vector with an modular type as index will give you good perfomace. Every Ada
-tutorial contains a expample on how to do it.
+From: Matthew Heaney
+Sent: Thursday, February 5, 2004  9:31 AM
 
-****************************************************************
+Robert A Duff wrote:
 
-From: Martin Krischik
-Sent: Saturday, February 7, 2004  6:14 AM
+> This stuff comes from the C++ STL.  I think gratuitous differences from
+> that are unhelpful.  (But I admit that I was one of the folks pushing
+> for "cursor" instead of "iterator".)
 
-> The committee selected the second proposal as a starting point for a
-> standard containers library, with a number of simple changes. The
-> changes were simple enough that we produced a version of the library with
-> the changes made (AI-00302-3/01).
+Yes.  The world has settled on the name "vector."  Let's use the terms
+everyone else is using, unless we have a good reason not to.
 
-Any place where I can actualy read the draft?
+(BTW, that's also why I used the name "Iterator_Type".  But I have no
+issues with the name "Cursor_Type".)
 
-Anyway, looking at the reference impementation vom Matthew Heaney (thanks for
-the quick responce) I have an improvements to suggest:
 
-type Element_Type is private;
+> I think "random access" is the essence of array semantics.  After all,
+> anything you can do with an array you can do with a linked list, and
+> vice versa -- the only fundamental difference is the efficiency
+> properties.
 
-I said this bevore that is too limiting. With that signature you can't even
-store strings. And more important you cant store Element'Class. In fact I
-predict that with that signature 80% of all data stored will be "access to
-something".
+But that's the essence of the argument!
 
-I have often heard Ada does not need garbage collection since a good container
-library should take care of memory management - and now I ready to follow
-that point. But taking that argument, vector is not a good container.
+Yes, it's *possible* to seek to specific elements in a linked list, but
+I would hardly call that "random access."
 
-Since vector will need heap storrage anyway and performace is only a minor
-issue I suggest:
+If you need fast random access to the elements in a container, and the
+number of elements in the container is large, then you can effectively
+rule out using a linked list as the container.
 
-type Element_Type (<>) is private;
+Of course you could make the argument the other way.  If you need
+constant-time insertion of elements at any position, then that
+effectively rules out a vector, in favor of a list.
 
 ****************************************************************
 
-From: Randy Brukardt
-Sent: Saturday, February 7, 2004  6:05 PM
+From: Alexandre E. Kopilovitch
+Sent: Thursday, February 5, 2004  3:21 PM
 
-> Any place where I can actualy read the draft?
+Robert A Duff wrote:
 
-The same place that you can read any other AI: www.ada-auth.org.
+> Bill Wulf and other professors at CMU circa late 1970's were using the
+> term "vector" to mean "array" (not necessarily extensible); that's the
+> first time *I* heard it.
 
-****************************************************************
+Yes, CMU always was (as far as I know) primarily engineering educational
+facility, and I know well that engineers (not software engineers, but rather
+general kind of engineers) often called "vector" any column or row of numbers.
+(not bothering themselves with the question how the components of that "vector"
+transform with a change of coordinate system). But apparently they never used
+this term for arrays of any other objects, and I almost never seen a case
+(even in engineering) where "vector" was used for extensible array - except
+Java and perhaps some C++ libraries.
 
-From: Martin Krischik
-Sent: Sunday, February 8, 2004  4:58 AM
+A notable exception is APL, in which "vector" is the basic term, and that
+"vector" is extensible. But in APL that "vector" is equipped with vast
+nomenclature of functions, many of them associated with genuine mathematical
+vectors, so the entire balance for the term was acceptable.
 
-I looked there but I only found a very long discussion but not the
-actual concluding decision.
+> So it's not a Java-ism.
 
-****************************************************************
+Yes, not exactly - there were other precedents of sloppy usage of this term.
+But nevertheless a strong impression remains that it is exactly Java, which
+is a real reason, ground and reference for proposing this term for extensible
+arrays *now and for Ada0Y*.
 
-From: Randy Brukardt
-Sent: Monday, February 9, 2004  6:03 PM
+> I think this meaning of "vector" derives from the maths meaning,
+> even if it's not precisely the same thing.
 
-Don't know what you're looking for, but certainly the entire AI is posted
-there. As with all AIs, the !wording section is what goes into the standard.
+No, not at all - it lacks the primary mathematical meaning of it, and adds
+the primary feature, which meaning is totally non-mathematical (that is, there
+is no attempt to bring any mathematical meaning to it... and it will not be
+simple, if attempted).
 
 ****************************************************************
+
+From: Matthew Heaney
+Sent: Thursday, February 5, 2004  5:11 PM
+
+
 
-From: Martin Krischik
-Sent: Saturday, February 7, 2004  6:24 AM
+Jeffrey Carter wrote:
 
-> > The only sequence container in the proposal is a vector,
+> The actual algorithm produces 8-bit hash values, which may no longer be
+> considered adequate, given
 >
-> Ah, yes, it's Sequence - quite right name for that container (and not
-> Vector).
+>> Hash_Type'Modulus shall be at least as large as the smaller of
+>> System.Max_Binary_Modulus and 2**32.
 
-No, in my book elements in a Sequence have only a relative positions, or at
-least the relative position is the primary position and absolut position is
-only the secondary.
+In Charles I copied the hash function from GNAT.  I figure if it's good
+enough for Robert Dewar it's good enough for me...
 
-That is: Get_Next (V); is faster or as fast as Get (V, 5);
 
-****************************************************************
 
-From: Martin Krischik
-Sent: Saturday, February 7, 2004  6:32 AM
+> Vector should have an iterator, in addition to allowing the user to
+> explicitly iterate over the structure.
 
-> My understanding of the model is that passive iterators are only for cases
-> where you want to iterate over the entire container.
+No.  Vector iterators are fragile, and hence very error prone.
 
-Yes.
+They are fragile because the (logical) internal array gets thrown away
+during expansion, which invalidates the iterator.  It's too hard to keep
+track of whether a vector iterator is still valid, and most of the time
+you end up with a dangling reference.
 
-> Indeed, given the iteration model of packages,
-> there's hardly any reason to use a passive iterator.
+The STL has vector iterators in order to provide the infrastructure
+necessary to support generic algorithms.
 
-Passive Iterators should allways provide the fastes mean to iterate over the
-hole container. They should do so by knowing the internals of the container.
+In Ada they are not necessary, because you can use locally-declared
+subprograms to fit within such a framework.
 
-Of course it only matters in advanced container with B-Trees or AVL-Trees as
-as internal structure. But I have only seen those in IBM's Open Class Library
-(which is far better the the STL).
 
-But there are no advanced containers in AI 302.
 
-****************************************************************
 
-From: Randy Brukardt
-Sent: Saturday, February 7, 2004  6:21 PM
+>> 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.
 
-> Passive Iterators should allways provide the fastes mean to iterate over the
-> hole container. They should do so by knowing the internals of the
-> container.
-
-That might be true in a language with a built-in iterator construct, but it
-is certainly not true in Ada because of the overhead of calling the generic
-formal subprogram for each element. In Janus/Ada, the overhead of calling a
-formal subprogram is at least double of a normal subprogram (we have to save
-and restore display information, because you could be calling into a more
-nested scope than the generic body -- something that normally isn't possible
-in Ada).
-
-Other compilers may not have that overhead, but they'll certainly have call
-overhead. Whereas, the explicit loop iterator for Vectors only needs to call
-Element. So the call overhead is at best a wash, and at worst much worse for
-the passive iterator. Moreover, the compiler is a lot more likely to be able
-to in-line the call to Element (which likely has a pretty simple
-implementation and thus will meet the in-lining qualifications), than the
-bunch of arbitrary code in the Process formal routine.
-
-So, a passive iterator will only be faster in complex containers (where you
-have to separate the  Element and Successor functions). For a Vector (where
-the language already has the needed iteration mechanism built-in), it's
-going to be slower (or, if you're really lucky, the same speed) and it
-certainly is a lot harder to write.
+Front can probably go away.  First is there for consistency with other
+containers.
 
-So I think having it on Vector would simply be for consistency; you'd never
-actually use it if you know you're dealing with a Vector.
 
-****************************************************************
 
-From: Robert A. Duff
-Sent: Saturday, February 7, 2004  7:22 PM
+> 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.
 
-> Other compilers may not have that overhead, but they'll certainly have call
-> overhead. Whereas, the explicit loop iterator for Vectors only needs to call
-> Element. So the call overhead is at best a wash, and at worst much worse for
-> the passive iterator. Moreover, the compiler is a lot more likely to be able
-> to in-line the call to Element (which likely has a pretty simple
-> implementation and thus will meet the in-lining qualifications), than the
-> bunch of arbitrary code in the Process formal routine.
-
-I don't see why the compiler shouldn't inline the Process routine,
-assuming the compiler isn't doing shared generics.  They're usually
-small, but anyway, the Process routine is typically called exactly
-once, so it shouldn't matter how big it is.
+That's not really possible for generic actual index types such as
+Natural or Positive.
 
-****************************************************************
+We could get rid of the assertion, but this would impact implementors.
+That's why it's still an open issue.
 
-From: Randy Brukardt
-Sent: Saturday, February 7, 2004  7:33 PM
+In my reference implementation, I don't think the generic actual type
+has to have IT'Base'First < IT'First, since internally I use Integer
+subtypes for everything.
 
-Most compilers have limitations on what can be inlined; Process (which
-contains arbitrary code) is far more likely to violate one of those
-limitations than Element (which never changes and is likely to be very
-simple). In addition, many compilers only inline when you give pragma
-Inline, and you can't do that on a generic formal.
+http://home.earthlink.net/~matthewjheaney/charles/ai302-20040205.zip
 
-****************************************************************
 
-From: Robert A. Duff
-Sent: Saturday, February 7, 2004  7:43 PM
 
-If Process violates whatever these arbitrary restrictions are, then
-sure, you can't get it inlined.  But typically Process is very simple --
-often just one line of code that calls some other procedure to do the
-real work, passing some additional parameters.  Process isn't a "real"
-procedure, conceptually -- it's just the body of a loop.
-
-In my current project, we make heavy use of the generic iterator
-pattern, and I think that in many many cases, Process is just
-a line or two of code.  (And if it's more, inlining is relatively
-less important.)
-
->... In addition, many compilers only inline when you give pragma
-> Inline, and you can't do that on a generic formal.
-
-You give the inline on the actual.  In non-sharing implementations,
-that should apply inside the instance.  And the iterator procedure
-itself can be inlined, too.
+> All the problems with Index_Type disappear with a general list, which
+> would use a cursor.
 
-****************************************************************
+The original proposal included list containers, but they were not
+included in the subcommittee report, in order to keep the size of the
+report more manageable.
 
-From: Randy Brukardt
-Sent: Saturday, February 7, 2004  8:04 PM
 
-Certainly it's not real (which is one thing I dislike about passive
-iterators in Ada - but we've discussed that before), but if it is very short
-(or the bodies of your loops are typically very short), then you're
-programming style must be very different from mine. The only loops that I
-write that are very short are those that I probably shouldn't have written
-in the first place (like the one finding the last '.' in a string) --
-there's a routine somewhere in Ada.Strings that will do the job, but looking
-it up is more work than writing the loop. (And a lot of them would be
-replaced by a Vector/List/Sequence container if I had one.)
-
-But just looking at the spam filter I'm working on at this moment: The
-average loop length is about 25 lines, the mean is around 8 lines. (There
-are more short loops than I would have guessed. But most of them wouldn't
-exist if I had a container to use instead - most of them are insert-at-end
-or delete-specific-item from a list.)
 
-...
-> You give the inline on the actual.  In non-sharing implementations,
-> that should apply inside the instance.  And the iterator procedure
-> itself can be inlined, too.
-
-At which point, you *equal* the performance of the active iterator. And only
-if *everything* goes right. The OP claimed that the passive iterator would
-always have better performance, and that's certainly not true for the vector
-container. I doubt that it would be true for the Map container, either. It
-could be true for a complex container, but those aren't commonly used.
+> 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.
 
-****************************************************************
+My original proposal had both sorted and hashed maps, but in order to
+keep the subcommittee report small support for sorted maps was removed.
 
-From: Alexandre E. Kopilovitch
-Sent: Saturday, February 7, 2004  7:55 PM
+
+> 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.
 
-Martin Krischik wrote:
+That's what the sorted set is for.
 
-> > > The only sequence container in the proposal is a vector,
-> >
-> > Ah, yes, it's Sequence - quite right name for that container (and not Vector).
->
-> No, in my book elements in a Sequence have only a relative positions, or at
-> least the relative position is the primary position and absolut position is
-> only the secondary.
-
-I don't know in which domain your book was grown up, but I can assure you that
-in mathematics (and by extension in physics and other natural sciences as they
-use mathematical apparatus) elements of a sequence are commonly indexed, and
-those indices are always treated as absolute position (which may be zero or
-even negative). By the way, your book is also certainly not from Biology/Genetics,
-where term "sequence" is used heavily, and they often speak about both absolute
-and relative positions in sequences.
-
-We have clearly different usage of terms "vector" and "sequence": substantial
-part of today's software engineering (tools and books) use them one way, while
-mathematics (and all natural sciences that use it heavily) always use them another
-way.
-
-So all the argument here about Vector/Sequence here is about Ada's choice of
-preference: will Ada choose software engineering (effectively, Java and C++
-libraries) side or mathematical/scientific side on this issue.
 
-I suppose (or hope) that the thesis "Ada is for problem space, not for solution
-space" implies the latter.
+> None of these applications use key/value pairs.
 
-****************************************************************
+So use the sorted set.
 
-From: Martin Krischik
-Sent: Sunday, February 8, 2004  11:40 AM
 
-> I don't know in which domain your book was grown up, but I can assure you
+> Therefore, I think it's
+> important to provide the underlying searchable structure to users.
 
-It's the english dictornary: "Aufeinanderfolge, Reihenfolge, Szene,
-Zeitfolge". Ah, you don't speak german. Well let's look for "Reihenfolge" in
-a rushian dictornary (and have a fight with my wives rushian keyboard):
-"???????????".
+Just use the sorted set container.  If guarantees that searches only
+take O (log N) even in the worst case.
 
-Asking my wives what it means she said "one after the other, queue".
 
-> that in mathematics (and by extension in physics and other natural sciences
-> as they use mathematical apparatus) elements of a sequence are commonly
-> indexed, and those indices are always treated as absolute position (which
-> may be zero or even negative). By the way, your book is also certainly not
-> from Biology/Genetics, where term "sequence" is used heavily, and they
-> often speak about both absolute and relative positions in sequences.
+> (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.)
 
-I have spend 4 years in Great Britain I am shure if I ask anyone on the street
-there "what is a sequence" he or she will answer somthing like "one after the
-other" - and that is relativ positioning.
+The (hashed) map stores the key and element as separate components of
+the internal node of storage.
 
-> We have clearly different usage of terms "vector" and "sequence":
-> substantial part of today's software engineering (tools and books) use them
-> one way, while mathematics (and all natural sciences that use it heavily)
-> always use them another way.
+If you have a record like that, containing a key-part component, then
+use the sorted set, and instantiate the nested generic package Generic_Keys.
 
-Even when it comes done to software engineering: IBM's Open Class Library has
-a Sequence - for relativ positioning  getFirst, getNext, insertAfter. Usualy
-used to fill listboxes.
 
-> So all the argument here about Vector/Sequence here is about Ada's choice
-> of preference: will Ada choose software engineering (effectively, Java and
-> C++ libraries) side or mathematical/scientific side on this issue.
+> 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?
 
-I don't like the STL that much. So I am not realy defending "vector".
+Yes, we really need string-key maps.
 
-> I suppose (or hope) that the thesis "Ada is for problem space, not for
-> solution space" implies the latter.
 
-I agree with you on that too.
+> 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.
 
-But I think we are off topic here.
+A "set" is really any sorted sequence of items.  If you want set
+intersection, symmetric difference, etc, then just use a generic
+algorithm.  See the Charles library for such algorithms.
 
-****************************************************************
+Of course, if you want target of a set union operation to be the set
+itself, then just use Insert to insert the items.
 
-From: Marius Amado Alves
-Sent: Saturday, February 7, 2004  8:41 PM
+The subcommittee report has several examples of how sets are used, and
+there's at least one example showing how to use the nested generic package.
 
-Randy Brukardt wrote:
+See the last two slides in my AE-2003 paper presentation for an example
+of how to take the union of a set and a (sorted) list:
 
->The 'committee' primarily adopted the existing proposal submitted by Matt
->Heaney. We decided not to change any of the major design decisions of that
->proposal - because no package will suit everyone or every need, and we felt
->it was more important to standardize something coherently designed for most
->needs than to fiddle endlessly with it and risk introducing serious bugs.
->
->Which is to say, I don't know. :-)
+http://home.earthlink.net/~matthewjheaney/charles/charlesppt.htm
 
-I do: there is none (except perhaps the implicit one: ease of
-implementation). On the other hand, there is a rationale for indefinite
-elements. This requirement has been largely felt and voiced since ever,
-and I included it in my Bases document (I think stored in alternative
-1), and even formulated it as an Annex (stored in alternative 2 but
-applicable to any alternative). But I've always seemed to feel some
-resistance from Matt and the ARG. Which resistance I find inexplicable.
-I really don't see how making the element type indefinite may
-"compromise coherence" or "introduce bugs". Sure it complicates the
-implementation. But the increase in power for the user is a quantum
-leap, as it frees him from doing tricky memory management in many
-situations. In my proposed Annex I included this passage from someone
-who should be dear to at least one person in that group--perhaps in the
-hope of making those strange walls of resistance just shiver a bit:
-
-<<If I ask a student whether her design is as good as Chartres, she often smiles tolerantly
-at me as if to say, "Of course not, that isnt't what I am trying to do.... I could never do
-that." Then, I express my disagreement, and tell her: "That standard *must* be our
-standard. If you are going to be a builder, no other standard is worthwhile.">>
-  -- Cristopher Alexander, Foreword to [Gabriel 1996]
+My original proposal has the same example at the very end:
 
-****************************************************************
+http://home.earthlink.net/~matthewjheaney/charles/ai302.txt
 
-From: Randy Brukardt
-Sent: Saturday, February 7, 2004  9:20 PM
 
-> I do: there is none (except perhaps the implicit one: ease of
-> implementation). On the other hand, there is a rationale for indefinite
-> elements.
 
-Perhaps. But that wasn't the question. The question was why aren't there
-indefinite *keys*.
+> "Sans" is a French word. Since the ARM is in English, we should use the
+> English "without" instead. "No" might also be acceptable.
 
-...
-> But I've always seemed to feel some
-> resistance from Matt and the ARG.
+Je crois que non.  C'est une bonne idea.
 
-Given that the "ARG" (other than the subcommittee) has not yet looked at
-these proposals, that's a pretty bizarre statement.
+The name for Delete_Sans_Increment comes from Emacs lisp, which has the
+functions file-name-sans-extension and file-name-sans-versions.
 
-...
-> I really don't see how making the element type indefinite may
-> "compromise coherence" or "introduce bugs". Sure it complicates the
-> implementation.
-
-And, on most implementations, I would expect it to make it *many* times
-slower. (It wouldn't have any effect on Janus/Ada, I don't think, because we
-already have to allocate an element at a time anyway.) I would guess that it
-is that efficiency concern that Matt is responding to. But I'll let him
-respond himself...
+It was also in homage to Ada's French history, given that her original
+designer was French, and worked for a French company.
 
-****************************************************************
+Why do you think "rendevous" was named that way?
 
-From: Marius Amado Alves
-Sent: Sunday, February 8, 2004  6:26 AM
 
->... that wasn't the question. The question was why aren't there
->indefinite *keys*.
->
-Oops... sorry.
 
-Curiously enough if you have indefinite elements the requirement for
-indefinite keys looses strength: you can then use elementary containers
-or indefinite element positions as keys.
+> 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.
 
->...
->
->>But I've always seemed to feel some
->>resistance from Matt and the ARG.
->
->Given that the "ARG" (other than the subcommittee) has not yet looked at
->these proposals, that's a pretty bizarre statement.
+If you don't immediately grok how vectors and sets and maps work, then I
+suggest familiarizing yourself with the STL. There are lots of tutorials
+on the WWW.
 
-Just a feeling. The proposals are there in the AI, and there was some
-discussion.
+I also recommend Stanley Lippman's little book Essential C++.  That was
+my introduction to the STL, and what originally convinced me that
+Stepanov's approach was the correct one.
 
->>I really don't see how making the element type indefinite may
->>"compromise coherence" or "introduce bugs". Sure it complicates the
->>implementation.
->
->And, on most implementations, I would expect it to make it *many* times
->slower....
+You might also like Accelerated C++ by Andrew Koenig and Barbara Moo,
+which uses the STL as a basis for teaching C++.
 
-No. The system should chose at compile time a specific body according to
-the 'Definite attribute of the actual element type.
+****************************************************************
 
-Aside. Of course there is still no standard means to do this, but it
-would be a nice extension. Conditional compilation of generic bodies
-based on instantiation properties. Variant units :-)
-  generic
-    type T is private;
-    ...
-  package G is
-    when T'Definite =>
-      ...;
-    when others =>
-      ...;
-  end;
-(On the subject of conditional compilation, see also the recent Ada
-Preprocessor thread on CLA.)
-In the meanwhile, there is no requirement that Ada.Containers be
-implemented strictly in Ada, is there? I doubt any Ada 95 container
-(arrays, files) is.
-End of aside.
+From: Randy Brukardt
+Sent: Thursday, February 5, 2004  5:49 PM
 
-So no coherence problem, nor bugs, nor efficiency problem :-)
+Matt's too modest. The tutorial that makes up the !example section is
+actually quite good. I learned a lot about how the packages work (and how to
+use them) from reading it carefully, and I recommend that everyone do that
+to better understand Matt's work.
 
 ****************************************************************
 
@@ -9571,8 +12041,8 @@
    If the Process procedure deletes the element designated by Cursor, or calls
    Update_Element on Cursor, Program_Error is raised.
 
-   AARM Note: This check has to be done in the code for Delete and Update_Element,
-   of course.
+   AARM Note: This check has to be done in the code for Delete and
+   Update_Element, of course.
 
 Making vector Update_Element safe would also require checking for any
 operations that would make the cursor ambigious. (That's a bounded error in

Questions? Ask the ACAA Technical Agent