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

Differences between 1.9 and version 1.10
Log of other versions for file ai12s/ai12-0212-1.txt

--- ai12s/ai12-0212-1.txt	2018/02/27 23:59:17	1.9
+++ ai12s/ai12-0212-1.txt	2018/03/02 05:05:52	1.10
@@ -1,4 +1,4 @@
-!standard 4.3.5(0)                                  18-02-14  AI12-0212-1/04
+!standard 4.3.5(0)                                  18-03-01  AI12-0212-1/05
 !class Amendment 16-12-27
 !status work item 17-06-10
 !status received 16-06-12
@@ -11,17 +11,18 @@
 
 !problem
 
-Currently, there are very few constructors for containers. We have for example
-the constant Empty_Set, and To_Set to construct a set containing the specified
-element. The best way to do this now is to manually assemble a new container
-with a series of statements; but this has a number of issues:
+Currently, there are very few constructors for containers. We have for
+example the constant Empty_Set, and To_Set to construct a set containing
+the specified element. The best way to do this now is to manually
+assemble a new container with a series of statements; but this has a
+number of issues:
 
    - cannot be used in a subprogram contract (such as a post condition)
    - can make code harder to read since construction has to be moved to a
      separate function
 
-An obvious approach would be to add functions that initialise a container from
-an aggregate of an unconstrained array, for example:
+An obvious approach would be to add functions that initialise a
+container from an aggregate of an unconstrained array, for example:
 
    X : Example.Set := Example.From_Array ((1, 2, 3));
 
@@ -31,23 +32,26 @@
 components), and it would only work for array-like containers and not
 maps.
 
-There are three places where container aggregates may be useful: in ordinary
-code (but here we can just do what we do right now), for the definition of
-constants, and in contracts.
+There are three places where container aggregates may be useful: in
+ordinary code (but here we can just do what we do right now), for the
+definition of constants, and in contracts.
 
 !proposal
 
 Thus, we propose to add a new aspect (in the spirit of Constant_Indexing,
-Default_Iterator, and Iterator_Element) along with two new aggregates to
-use it, based on the array aggregate syntax.
+Default_Iterator, and Iterator_Element) along with a new kind of aggregate to
+use it, inspired by the array aggregate syntax.
+Thus, we propose to add a new aspect (in the spirit of Constant_Indexing,
+Default_Iterator, and Iterator_Element) along with a new kind of aggregate to
+use it, inspired by the array aggregate syntax.
 
 This proposal works for most of the standard containers (Vectors,
 Doubly_Linked_Lists, Hashed_Sets, Ordered_Sets, Hashed_Maps and
 Ordered_Maps including their bounded and indefinite versions).
 Multiway_Trees are not supported by this proposal.
 
-The concept is inspired by Python and other languages that have list and
-set "comprehensions," but it uses, largely, Ada's array aggregate as the
+The concept is inspired in part by Python and other languages that have list
+and set "comprehensions," but it uses, largely, Ada's array aggregate as the
 basis for the syntax.
 
 In the most simple form (called a positional container aggregate) we
@@ -97,7 +101,8 @@
    end loop;
 
 Finally, it is also a common pattern to combine multiple containers into
-one. Three approaches are supported. This is the nested (or "product") one:
+one. Three approaches are considered. This is the nested (or "product") one
+(note that this is not part of the current proposal):
 
    W : My_Set := (for A of X =>
                     for B of X => A * B);  --  TBD: Not currently in this AI
@@ -110,7 +115,9 @@
       end loop;
    end loop;
 
-This is the sequential (or "list") one:
+This is the sequential (or "list") one (this is based on the similar
+capability in the array aggregate to have multiple iterated component
+associations in a single aggregate:
 
    V : My_Set := (for A of X => A,
                   for A of X => -A);
@@ -124,7 +131,11 @@
       Include (V, -A);
    end loop;
 
-This is the concurrent one (TBD --  not in this AI yet):
+This is the concurrent one (note that this is not part of the current
+proposal, and would more properly be associated with a general
+enhancement to iterators -- this is not "parallel" but rather "concurrent"
+in that the two iterators are advanced concurrently, stopping when
+either one finishes):
 
    V : My_Set := (for (A of X; I in 1..Max) => (A, I));
    -- TBD: Not currently in this AI yet
@@ -138,7 +149,7 @@
    --  where the parenthesized iterators run concurrently, with the iteration
    --  stopping when either runs out of elements.
 
-The new contract on the set container would be:
+The new aspect specifications for the set container would be:
 
    type Set is tagged private
       with --  currently we have this:
@@ -164,34 +175,57 @@
 where "Insert" is specified as the "Add_Named" component of the
 Aggregate aspect.
 
+To accommodate array-like containers that require a contiguous
+range of "key" values, and might not be extensible, we allow the
+specification of a New_Indexed function that creates an indexed
+structure with the appropriate bounds, and an Assign_Indexed procedure
+that assigns a value into a particular indexed element.
+Aggregates that use these operations are called "indexed aggregates"
+and have many of the same rules as array aggregates with respect to
+uniqueness of indices and full coverage.
+
 So, to summarise:
-* New aspect on types specifying an empty default, plus either an
-  Add_Positional or an Add_Named procedure (or both).
+* New aspect on types specifying an empty default, plus an
+  Add_Positional, and either an Add_Named procedure or Assign_Indexed
+  procedure (with a New_Indexed function to go with it).
 * Extend aggregate syntax to trigger these
 
 !wording
+
+Modify 13.1.1(5/3):
+
+  An aspect_mark identifies an aspect of the entity defined by the
+  associated declaration (the associated entity); the aspect denotes an
+  object, a value, an expression{, an aggregate}, a subprogram, or some
+  other kind of entity. If the aspect_mark identifies:
 
-4.3 Aggregates
+Add after 13.1.1(7/3):
 
-Change paragraph 2/5:
+  * an aspect that is an aggregate, the aspect definition shall be
+    an expression that is an aggregate, with the form of the
+    aggregate determined by the identified aspect;
 
+Replace 4.3(2/5):
+
    aggregate ::= record_aggregate | extension_aggregate | array_aggregate
                | delta_aggregate
 
-To:
+with:
 
    aggregate ::= record_aggregate | extension_aggregate | array_aggregate
                | delta_aggregate | container_aggregate
 
-Modify paragraph 3/5:
+Modify 4.3(3/5):
 
   The expected type for a delta_aggregate shall be a single array type,
   or a single descendant of a record type or of a record extension. The
   expected type for any other aggregate shall be a single array type,
   record type, [or ]record extension{, or other composite type with the
   Aggregate aspect specified}.
+
+Add new section:
 
-Add new section: 4.3.5 Container Aggregates
+4.3.5 Container Aggregates
 
 In a container_aggregate, values are specified for elements of a
 container; for a positional_container_aggregate, the elements are given
@@ -207,13 +241,18 @@
   kind of aggregate, since syntactically it is indistinguishable.
 
   Aggregate
-    This aspect is of the form:
+    This aspect is an aggregate of the form:
 
       (Empty => name[,
        Add_Positional => /procedure_/name][,
-       Add_Named => /procedure_/name])
-
-    Either Add_Positional, Add_Named, or both shall be specified.
+       Add_Named => /procedure_/name][,
+       New_Indexed => /function_/name,
+       Assign_Indexed => /procedure_/name])
+
+    A /procedure_/name shall be specified for at least one of
+    Add_Positional, Add_Named, or Assign_Indexed.  A /procedure_/name shall
+    be specified for at most one of Add_Named or Assign_Indexed.  Either both
+    or neither of New_Indexed and Assign_Indexed shall be specified.
 
 Name Resolution Rules
 
@@ -230,24 +269,35 @@
       but it is not required to do so.
 
     The /procedure_/name specified for Add_Positional, if any, shall
-    have two parameters, the first an IN OUT parameter of type T,
-    and the second an IN parameter of some nonlimited type, called
-    the /element type/ of T.
-
-    The /procedure_/name specified for Add_Named, if any, shall have
-    three parameters, the first an IN OUT parameter of type T,
-    the second an IN parameter of a nonlimited type, that is called the
-    /key type/ of the container, and the third, an IN parameter of a
-    nonlimited type that is called the /element type/ of T.
+    denote a procedure that has two parameters, the first an IN OUT
+    parameter of type T, and the second an IN parameter of some
+    nonlimited type, called the /element type/ of T.
+
+    The /function_/name specified for New_Indexed, if any, shall denote
+    a function with a result type of T, and two parameters of the same
+    discrete type, with that type being the /key type/ of the container.
+      AARM Reason: The New_Indexed function is used instead of Empty
+      as the first step of creating an aggregate that is initialized
+      using the Assign_Indexed procedure.
+
+    The /procedure_/name specified for Add_Named or Assign_Indexed, if any,
+    shall denote a procedure that has three parameters, the first an IN
+    OUT parameter of type T, the second an IN parameter of a nonlimited
+    type (the /key type/ of the container), and the third,
+    an IN parameter of a nonlimited type that is called the /element
+    type/ of T.  In the case of Assign_Indexed, the key type shall be the
+    same type as that of the parameters of New_Indexed.
+
+    If both Add_Positional and either Add_Named or Assign_Indexed are
+    specified, the final parameters shall be of the same type -- the
+    element type of T.
 
-    If both Add_Positional and Add_Named are specified, the final
-    parameters shall be of the same type -- the element type of T.
-
-
 Syntax
+
+   container_aggregate ::= empty_container_aggregate
+     | positional_container_aggregate | named_container_aggregate
 
-   container_aggregate ::=
-     positional_container_aggregate | named_container_aggregate
+   empty_container_aggregate ::= (<>)
 
    positional_container_aggregate ::= (expression, expression {, expression})
 
@@ -275,39 +325,102 @@
 
 The expected type for a positional_container_aggregate shall have an
 Aggregate aspect that includes a specification for an Add_Positional
-procedure.  The expected type for a named_container_aggregate that has
-one or more /key_/expressions shall have an Aggregate aspect that
-includes a specification for the Add_Named procedure.  The expected type
-for each such /key_/expression is the key type of the expected type.
+procedure or an Assign_Indexed procedure.  The expected type for a
+named_container_aggregate that has one or more /key_/expressions shall
+have an Aggregate aspect that includes a specification for the Add_Named
+or Assign_Indexed procedure.  The expected type for each such
+/key_/expression is the key type of the expected type. [Redundant: An
+empty_container_aggregate may be used with any expected type that has an
+Aggregate aspect.]
 
 Legality Rules
 
+If the expected type T of an aggregate specifies an Assign_Indexed
+procedure in its Aggregate aspect, then the aggregate is called an
+/indexed aggregate/ if there is no Add_Positional procedure specified,
+or if the aggregate is a named_container_aggregate with a
+container_element_association that has a key_expression_list,
+or that has a loop_parameter_specification.  The key type of an indexed
+aggregate is also called the /index type/ of the aggregate.
+
 For an iterated_element_association without a /key_/expression, if the
 expected type T of the aggregate does not specify an Add_Positional
-procedure in its Aggregate aspect, then the type of the loop parameter
-of the iterated_element_association shall be the same as the key type of T.
+procedure in its Aggregate aspect, or if the aggregate is an indexed
+aggregate, then the type of the loop parameter of the
+iterated_element_association shall be the same as the key type of T.
   AARM Ramification: If there is a /key_/expression in an
   iterated_element_association, it determines the key of each added
   key/value pair, rather than the loop parameter.  If there is no
-  /key_/expression, the loop parameter itself is used as the key.
+  /key_/expression, the loop parameter itself is used as the key,
+  and for Assign_Indexed, the iterated_element_association must
+  be over a contiguous discrete range.
+
+For a named_container_aggregate that is an indexed aggregate,
+all container_element_associations shall either have a
+key_expression_list or have a loop_parameter_specification.
+Furthermore, for such an aggregate, either:
+  * all /key_/expressions shall be static expressions, and every
+    loop_parameter_specification shall have a
+    discrete_subtype_definition that defines a non-null static range,
+    and the set of values of the index type covered by the
+    /key_/expressions and the discrete_subtype_definitions shall form a
+    contiguous range of values with no duplications; or
+  * there shall be exactly one container_element_association, and if
+    it has a key_expression_list, the list shall have exactly one
+    /key_/expression.
+      AARM Reason: The above is trying to mimic the rules for named array
+      aggregates, without others.
 
 Dynamic Semantics
 
 The evaluation of a container_aggregate starts by creating an anonymous
-object A of the expected type T initialized by assignment from the Empty
-constant, or from a call on the Empty function specified in the Aggregate
-aspect.  In the case of an Empty function, the parameter, if any, is
-initialized as follows:
-   * for a positional_container_aggregate, the number of expressions;
-   * for a named_container_aggregate without an iterated_element_association,
-     the number of container_element_associations;
-   * otherwise, to an implementation-defined value.
+object A of the expected type T initialized as follows:
+   * if the aggregate is an indexed aggregate, from the result of a call
+     on the New_Indexed function; the actual parameters in this call
+     represent the first and last index of the aggregate, and are determined
+     as follows:
+      * if the aggregate is a positional_container_aggregate, the first index
+        is the low bound of the subtype of the key parameter of the
+        Add_Indexed procedure, and the last index has a position number
+        that is the sum of the position number of the first index and
+        one less than the number of expressions in the aggregate;
+      * if the aggregate is a named_container_aggregate, the first index
+        is the lowest value appearing either within a key_expression_list or
+        as the low bound of a range defined by a discrete_subtype_definition
+        of a loop_parameter_specification; the last index is the highest
+        vale appearing either within a key_expression_list or as the high
+        bound of a range defined by a discrete_subtype_definition of a
+        loop_parameter_specification.
+   * if the aggregate is not an indexed aggregate, by assignment from the
+     Empty constant, or from a call on the Empty function specified in
+     the Aggregate aspect.  In the case of an Empty function with a formal
+     parameter, the actual parameter has the following value:
+      * for an empty_container_aggregate, the value zero;
+      * for a positional_container_aggregate, the number of expressions;
+      * for a named_container_aggregate without an iterated_element_association,
+        the number of /key_/expressions;
+      * for a named_container_aggregate where every iterated_element_association
+        is of the form with a loop_parameter_specification, the total
+        number of elements specified by all of the
+        container_element_associations;
+      * otherwise, to an implementation-defined value.
 
 The evaluation then proceeds as follows:
-  * for a positional_container_aggregate, each expression is evaluated
-    in an arbitrary order, and the Add_Positional procedure is invoked in
-    sequence with the anonymous object A as the first parameter and the
-    result of evaluating each expression in the order of the expressions;
+  * for an empty_container_aggregate, the anonymous object A is the result;
+  * for a positional_container_aggregate of a type with a specified
+    Add_Positional procedure, each expression is evaluated
+    in an arbitrary order, and the Add_Positional procedure is invoked
+    in sequence with the anonymous object A as the first parameter and
+    the result of evaluating each expression as the second parameter, in
+    the order of the expressions;
+  * for a positional_container_aggregate that is an indexed aggregate,
+    each expression is evaluated in an arbitrary
+    order, and the Assign_Indexed procedure is invoked in sequence with the
+    anonymous object A as the first parameter, the key value as the
+    second parameter, computed by starting with the low bound of the
+    subtype of the key formal parameter of the Assign_Indexed procedure and
+    taking the successor of this value for each successive expression,
+    and the result of evaluating each expression as the third parameter;
   * for a named_container_aggregate for a type with an Add_Named procedure
     in its Aggregate aspect, the container_element_associations are evaluated
     in an arbitrary order:
@@ -328,8 +441,10 @@
           * if there is a /key_/expression, the result of evaluating
             the /key_/expression as the second parameter;
           * otherwise, with the loop parameter as the second parameter;
-   * for a named_container_aggregate for a type without an Add_Named
-     procedure in its Aggregate aspect, the container_element_associations
+   * for a named_container_aggregate that is an indexed aggregate, the
+     evaluation proceeds as above for the case of Add_Named, but with
+     the Assign_Indexed procedure being invoked in its stead;
+   * for any other named_container_aggregate, the container_element_associations
      (which are necessarily iterated_element_associations)
      are evaluated in the order given:
        * the iterated_element_association is elaborated, and an iteration
@@ -344,11 +459,11 @@
 
 Examples
 
-Declarations of Set_Type and Map_Type:
+Declarations of Set_Type, Map_Type, and Vector_Type:
 
    --  Set_Type is a set-like container type.
    type Set_Type is private
-     with Aggregate => (Empty          => Empty_Set;
+     with Aggregate => (Empty          => Empty_Set,
                         Add_Positional => Include);
    function Empty_Set return Set_Type;
 
@@ -358,13 +473,32 @@
 
    --  Map_Type is a map-like container type.
    type Map_Type is private
-     with Aggregate =>  (Empty      => Empty_Map;
+     with Aggregate =>  (Empty      => Empty_Map,
                          Add_Named  => Add_To_Map);
 
    procedure Add_To_Map (M : in out Map_Type; Key : Integer; Value : String);
 
    Empty_Map : constant Map_Type;
 
+   --  Vector_Type is an extensible array-like container type.
+   type Vector_Type is private
+      with Aggregate => (Empty          => Empty_Vector,
+                         Add_Positional => Append_One,
+                         New_Indexed    => New_Vector,
+                         Assign_Indexed => Assign_Element)
+
+   function Empty_Vector (Capacity : Count_Type := 0) return Vector_Type;
+
+   procedure Append_One (V : in out Vector_Type; New_Item : String);
+
+   procedure Assign_Element (V : in out Vector_Type; Index : Positive;
+                             Item : String);
+
+   function New_Vector (First, Last : Positive) return Vector_Type
+     with Pre => First = Positive'First;
+       --  Vectors of are always indexed starting at the
+       --  low bound of their index subtype.
+
  private
 
    type Set_Type is new Bit_Vector (Small_Natural); -- see 3.6
@@ -383,8 +517,20 @@
    Empty_Map : constant Map_Type :=
      (Int_String_Maps.Empty_Map with null record);
 
-Examples of container aggregates for Set_Type and Map_Type
+   package String_Vectors is
+     new Ada.Containers.Indefinite_Vectors -- see A.18.
+       (Index_Type => Positive, Element_Type => String);
 
+   type Vector_Type is new String_Vectors.Vector;
+
+Examples of container aggregates for Set_Type, Map_Type, and Vector_Type
+
+   --  Assign S to an empty set
+   S := (<>);
+
+   --  Is Equivalent to:
+   S := Empty_Set;
+
    --  A positional set aggregate
    S := (1, 2);
 
@@ -454,10 +600,16 @@
          end if;
       end loop;
    end loop;
-
 
+   --  Example aggregates using Map_Type
    M : Map_Type;
 
+   --  Create an empty map
+   M := (<>);
+
+   --  is equivalent to:
+   M := Empty_Map;
+
    --  A simple named map aggregate
    M := (12 => "house", 14 => "beige");
 
@@ -503,6 +655,51 @@
    --  The above could have been written using an explicit key_expression:
    M := (for Key of Keys, Key => Integer'Image (Key));
 
+   --  Example aggregates using Vector_Type
+   V : Vector_Type;
+
+   --  Create an empty vector aggregate
+   V := (<>);
+
+   --  Is equivalent to:
+   V := Empty_Vector (0);
+
+   --  A positional vector aggregate
+   V := ("abc", "def");
+
+   --  Is equivalent to:
+   V := Empty_Vector (2);
+   Append_One (V, "abc");
+   Append_One (V, "def");
+
+   --  An indexed vector aggregate
+   V := (1 => "this", 2 => "is", 3 => "a", 4 => "test");
+
+   --  Is equivalent to:
+   V := New_Vector (1, 4);
+   Assign_Element (V, 1, "this");
+   Assign_Element (V, 2, "is");
+   Assign_Element (V, 3, "a");
+   Assign_Element (V, 4, "test");
+
+   --  A vector of images of dynamic length
+   V := (for I in 1 .. N => Integer'Image (I));
+
+   --  is equivalent to:
+   V := New_Vector (1, N);
+   for I in 1 .. N loop
+      Assign_Element (V, I, Integer'Image (I));
+   end loop;
+
+   --  A vector made from the elements of a map
+   V := (for Elem of M => Elem);
+
+   --  is equivalent to:
+   V := Empty_Vector (<estimate of size of M>);
+   for Elem of M loop
+      Add_Positional (V, Elem);
+   end loop;
+
 A.18.2 The Generic Package Containers.Vectors
 
 Add the Aggregate aspect to the existing ones on type Vector:
@@ -513,7 +710,17 @@
            Default_Iterator  => Iterate,
            Iterator_Element  => Element_Type,
            Aggregate         => (Empty          => Empty_Vector,
-                                 Add_Positional => Append);
+                                 Add_Positional => Append_One,
+                                 New_Indexed    => New_Vector,
+                                 Assign_Indexed => Replace_Element);
+
+   --  Need to add these subprograms:
+   function New_Vector (First, Last : Index_Type) return Vector
+     is (To_Vector (Last))
+     with Pre => First = Index_Type'First;
+
+   procedure Append_One (Container : in out Vector;
+                         New_Item  : in     Element_Type);
 
 A.18.3 The Generic Package Containers.Doubly_Linked_Lists
 
@@ -589,7 +796,6 @@
 iteration efficiently and determine an upper bound for the size of the
 array.
 
-
 We use a simple "," to separate the iterator from the key => value
 when there is an explicit key_expression:
 
@@ -1928,4 +2134,292 @@
 
 That's all I have at this point.
   
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, February 28, 2018  6:05 AM
+
+>> Here is an update, with Jeff's corrections. 
+> 
+> I'm just getting around to reading this. Comments:
+> 
+> For some reason, you numbered this "version 5" (and the previous one 
+> "version 4"), but there never was a version 3. So you are off by one 
+> for the version numbers. (This one was posted as version /04.)
+
+Sorry about that.
+
+> 
+> ---
+> 
+> The syntax for aspect Aggregate separates the parts with commas, but 
+> the examples use semicolons. (I'd expect commas to be consistent with 
+> similar syntax elsewhere in Ada, but whatever it is should be 
+> consistent.)
+
+Oops.  Definitely meant to use "," since we want these to look like aggregates.
+> 
+> ---
+> 
+> 13.1.1 gives a list of things that can be an aspect. This new syntax 
+> for aspect Aggregate is not one of those things. Note that when I was 
+> faced with a similar issue for aspect Stable_Properties, I extended 
+> the syntax in 13.1.1. We do have a blanket "alternative rules may 
+> apply" statement, but it would be best if we made all of the 
+> language-defined aspects as consistent as possible. One possibility 
+> would be to make "aggregate" a syntactic choice here, and then redo 
+> Stable_Properties in terms of that (stable properties needing a list, for
+> which positional aggregate syntax would be fine).
+> 
+> Maybe we should do that here, maybe in another AI.
+
+I would do it here.  Interdependent AIs are a bit of a pain.
+ 
+> ---
+> 
+> You and I have swapped positions on the iterated choices. :-) I now 
+> think that they ought to be treated like others (which isn't allowed 
+> here) -- that is, they can appear in positional aggregates, but only if they
+> appear last. That's the only way to make vector and array aggregates near 
+> identical, because the iterated choice (except for the "traditional" 
+> discrete range
+> one) doesn't provide the indexes needed for a named array aggregate. 
+> And all of them (again except for the "traditional" discrete range 
+> one) can't appear in a named array aggregate without a key expression 
+> (which is really the index expression for an array aggregate).
+
+I am not really following this.  Could you give an example or two?
+
+> We probably need to figure out the array aggregate rules for this, 
+> because it doesn't do for container aggregates and array aggregates to 
+> work very differently in this case (or any case, when it comes to vector
+> aggregates).
+> 
+> ---
+> 
+> Erhard complained about using "," to represent sequentiality -- but 
+> this is an aggregate, and the choices can be evaluated in an arbitrary 
+> order. Ergo, it ISN'T representing sequentiality, just proximity. ";" 
+> (which does represent sequentiality) would be wrong.
+
+I agree -- "," is used to separate elements in an aggregate, whether they are
+iterated component associations or simple "<range> => value" associations.
+
+> 
+> ---
+> 
+> If we want array and vector aggregates to really be similar, then we 
+> need a named vector aggregate option. This would best be somewhat 
+> separate from the map aggregate, so that the requirements on named 
+> array and vector aggregates are identical.
+> 
+> Ergo, I'd suggest a third choice (maybe "Add_Indexed") which requires 
+> that the key type is discrete; then choices that are ranges would be 
+> allowed, and non-overlap checking (with the only one dynamic choice 
+> rule) could be enforced. Essentially, the legality rules would match 
+> an array aggregate sans "others" (no others as there is no sane way to 
+> get an applicable index constraint). (The dynamic rules would be essentially
+> the same as Add_Named).
+
+I agree -- Add_Indexed sounds useful, and should be distinct from Add_Named.
+ 
+> ---
+> 
+> That's all I have at this point.
+
+Thanks.  I'll try to send out a quick update, with at least some of this.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, February 28, 2018  4:58 PM
+
+Steve Baird wrote (privately):
+
+> Would any mention of container delta aggregates be premature?
+
+Interesting.  That sort of makes sense.  You'd want that in a post-condition.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, February 28, 2018  5:44 PM
+
+I'd suggest treating that as a separate AI, simply to avoid loading too much
+stuff into a single AI. (Unless it turns out to be effectively trivial.) But
+it does seem like it fits into the notion that a Vector aggregate and an array
+aggregate are as similar in functionality as we can make them.
+
+Note that since delta aggregates only work for named notation, such container
+aggregates would only be meaningful for "Add_Named" and "Add_Indexed" cases. 
+Meaning that Lists and Sets couldn't use them -- annoying, but understandable.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, February 28, 2018  6:08 PM
+
+...
+> > You and I have swapped positions on the iterated choices. :-) I now 
+> > think that they ought to be treated like others (which isn't allowed
+> > here) -- that is, they can appear in positional aggregates, but only 
+> > if they appear last.
+> > That's the only way to make vector and array aggregates near 
+> > identical, because the iterated choice (except for the "traditional"
+> > discrete range
+> > one) doesn't provide the indexes needed for a named array aggregate. 
+> > And all of them (again except for the "traditional" discrete range
+> > one) can't appear in a named array aggregate without a key 
+> > expression (which is really the index expression for an array aggregate).
+> 
+> I am not really following this.  Could you give an example or two?
+
+Array aggregates in Ada have some restrictions on them in order to ease 
+implementation, for instance the only dynamic part of a positional aggregate
+has to be the last one, and there can only be a single dynamic part in a named
+aggregate. I've been assuming that we'd want to preserve some version of this
+going forward (so we aren't allowing arbitrary dynamic iterators in array 
+aggregates) -- if we wanted to relax these sorts of restrictions, we
+definitely need to do that generally and not just in this one special case.
+(The effort to implement is about the same for all of these cases.)
+
+Anyway, container iterators used in an array aggregate have to be treated as
+part of a positional aggregate, as they don't provide any index values (so
+they *can't* be a named aggregate). For example:
+
+      Some_List : ... -- A list container of Natural.
+      
+      type Some_Array is array (Positive range <>) of Natural;
+
+      Agg1 : Some_Array := (for E of Some_List => E);
+          -- This has to be treated as a positional array aggregate as the
+          -- choice provide no array indexes. "others" isn't allowed here,
+          -- so we can't even get them from the environment.
+
+      Agg2 : Some_Array := (for I in Agg1'Range => Agg1(I));
+          -- This is currently a named aggregate, since it is dynamic it can
+          -- be the only choice here.
+      Agg3 : Some_Array := (for E of Agg1 => E;
+          -- This could go either way, as the indexes could be implied from 
+          -- those of Agg1, or ignored (since they're not explicit)
+      Agg4 : Some_Array := (for C in Some_List.Iterator => Some_List.Element(C));
+          -- Has to be positional, again there is no source for array indexes.
+
+      Agg5 : Some_Array := (1, 2, 3, for E of Some_List => E);
+          -- A positional aggregate, but no harder to implement than the
+          -- existing cases.
+      Agg6 : Some_Array := (1, 2, for E of Some_List => E, 4, 5);
+          -- A positional aggregate, but with the dynamic part in the middle.
+          -- Ugh. Readability isn't good, either (the trailing choices get
+          -- lost). Ada currently doesn't allow this.
+      Agg7 : Some_Array := (1 => 2, 2 => 4, for E of Some_List => E);
+          -- Hopefully illegal, as the bounds of the iterator aren't defined.
+          -- To make this work, we'd have to "imply" the bounds from the other
+          -- choices. But that would require making the unordered (a named
+          -- array aggregate) ordered in some sense. And then what to do if
+          -- there aren't other choices available?
+
+So, we either have to treat these iterators similarly to "others" and allow
+them (only?) in positional aggregates, or treat them exactly like "others"
+and allow them only when the bounds come from context. I preferred the first
+of these when I thought about it, because it would likely to be annoying to 
+have to pre-figure the bounds (and declare an appropriate subtype) when these
+aggregates are passed as parameters (with unconstrained formal types) or when
+used in preconditions/postconditions (declaring an bounded subtype might not 
+be possible if other parameters are involved).
+
+However this works for arrays, container aggregates ought to be similar, just
+so we aren't giving unintended incentives to use containers rather than arrays
+(or vice versa).
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, March 1, 2018  8:37 AM
+
+Here is a new version [this is version /05 of the AI - ED.] that incorporates
+Randy's idea of "indexed" aggregates,
+where they require a contiguous no-duplicates range of indices in a named 
+aggregate.  This was more work than I originally anticipated, because we need
+to create the object in advance with bounds determined from the names, and
+then assign individual values.  I introduced the term "indexed aggregates" to
+avoid having to keep repeating the circumstances under which the new
+New_Indexed/Assign_Indexed routines would be invoked.
+
+The net result of this is that now you can use named aggregates with Vectors, 
+and get the same level of checking as is provided for a named array aggregate
+(full coverage, etc.).
+
+I did *not* try to incorporate Randy's idea of positional aggregate with a
+single iterated-element-association at the end.  It seems easy enough to
+require the whole aggregate to be named in that case.  A mixture of positional
+and named just seemed too weird, except for the special case of
+"others => blah" which depends on the "applicable index constraint" notion
+that doesn't generalize to container aggregates.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 1, 2018  10:19 PM
+
+...
+> I did *not* try to incorporate Randy's idea of positional aggregate 
+> with a single iterated-element-association at the end.  It seems easy 
+> enough to require the whole aggregate to be named in that case.  A 
+> mixture of positional and named just seemed too weird, except for the 
+> special case of "others => blah" which depends on the "applicable 
+> index constraint"
+> notion that doesn't generalize to container aggregates.
+
+But then you can't use them at all in "Add_Indexed" or array aggregates,
+because they do not have any way to have bounds. Unless you plan to define
+a whole new set of bounds rules -- and even that would have to limit them to
+one iterator per aggregate (I sure hope we're not planning to dump the "one 
+dynamic choice" rule only in this weird case). That doesn't seem to be the way
+you wanted to go -- but perhaps you've decided to abandon iterators in
+aggregates except in the map case???
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, March 1, 2018  11:03 PM
+
+> Here is a new version ...
+
+Now for a few comments on the actual text:
+
+>So, to summarise:
+>* New aspect on types specifying an empty default, plus an
+>  Add_Positional, and either an Add_Named procedure or Assign_Indexed
+>  procedure (with a New_Indexed function to go with it).
+>* Extend aggregate syntax to trigger these
+
+This second bullet seems like 1/2 of a thought. "trigger these" what? There 
+doesn't seem to be any extension of aggregate syntax needed here (that should
+happen in array aggregates, as previously discussed, and should really happen
+first so we don't end up with a hodge-podge of rules).
+
+>Modify 13.1.1(5/3):
+>  An aspect_mark identifies an aspect of the entity defined by the
+>  associated declaration (the associated entity); the aspect denotes an
+>  object, a value, an expression{, an aggregate}, a subprogram, or some
+>  other kind of entity. If the aspect_mark identifies:
+
+Don't we need to add "aggregate" to the syntax? It's rather confusing to have 
+it implicit as part of expression and we already have "name" which also
+completely overlaps with "expression".
+
+Side question: should we go back and change the syntax of Stable_Properties to
+an aggregate? Or just leave well enough alone??
+
+>   key_expression_list ::= /key_/expression {| /key_/expression}
+
+No discrete_ranges here for the case of an indexed aggregate (array aggregates
+definitely allow that). Intentional (and why?) or mistake?
+
+There really is a lot of examples; it seems like too many for the RM. (This is
+inverse of the usual problem.) I have to wonder if we need all of the
+equivalences in the RM (as opposed to in the !examples section of the AI). But
+we do need *some* examples in the RM.
+
 ****************************************************************

Questions? Ask the ACAA Technical Agent