4.3 Aggregates
This Reference Manual output has not been verified, and may contain omissions or errors. Report any problems on the tracking issue
[ An aggregate combines component values into a composite value of an array type, record type, or record extension.]
Syntax
3/5aggregate
::=
record_aggregate
| extension_aggregate
| array_aggregate
| delta_aggregate
| container_aggregate
Name Resolution Rules
4/5The expected type for an aggregate
shall be a single array type, a single type with the Aggregate aspect specified, or a single descendant of a record type or of a record extension.
aggregate
s to resolve them. For instance, Ada 95 allowed array types to match extension_aggregate
s, even though those have to be record types. Thus, we allow any record type with any visible (nondiscriminant) components to match an aggregate
, even though only delta_aggregate
s allow private types or private extensions. Similarly, we allow any container type to match an aggregate
, even though only container_aggregate
s allow container types. Legality Rules
5/5A record_aggregate
or extension_aggregate
shall not be of a class-wide type.
aggregate
s of a type with unknown discriminants. However, that was unnecessarily restrictive in the case of an extension aggregate, and irrelevant to a record aggregate (since a type that is legal for a record aggregate could not possibly have unknown discriminants) and to an array aggregate (the only specific types that can have unknown discriminants are private types, private extensions, and types derived from them). delta_aggregate
s, as those can get the specific type from the object represented by the base_expression
(possibly at run time). We don't mention array_aggregate
s, as those cannot even be of a tagged type, so being class-wide is impossible. Dynamic Semantics
6For the evaluation of an aggregate
, an anonymous object is created and values for the components or ancestor part are obtained (as described in the subsequent subclause for each kind of the aggregate
) and assigned into the corresponding components or ancestor part of the anonymous object. Obtaining the values and the assignments occur in an arbitrary order. The value of the aggregate
is the value of this object.
ancestor_part
is the expression
or subtype_mark
that specifies how the ancestor part of the anonymous object should be initialized. ancestor_part
is a subtype_mark
the Initialize procedure for the ancestor type is applied to the ancestor part after default-initializing it, unless the procedure is abstract, as described in 7.6. The Adjust procedure for the ancestor type is not called in this case, since there is no assignment to the ancestor part as a whole. If an aggregate
is of a tagged type, a check is made that its value belongs to the first subtype of the type. Constraint_Error is raised if this check fails.
Extensions to Ada 83
extension_aggregate
s. Wording Changes from Ada 83
Incompatibilities With Ada 95
type Lim is limited
record
Comp: Integer;
end record;
7.g/2type Not_Lim is
record
Comp: Integer;
end record;
7.h/2procedure P(X: Lim);
procedure P(X: Not_Lim);
7.i/2P((Comp => 123)); -- Illegal in Ada 2005, legal in Ada 95
aggregate
could not have a limited type. Qualifying the aggregate
will eliminate any ambiguity. This construction would be rather confusing to a maintenance programmer, so it should be avoided, and thus we expect it to be rare. Extensions to Ada 95
Incompatibilities With Ada 2012
aggregate
. These types are only allowed for new types of aggregate
(container_aggregate
s for the Aggregate aspect, and delta_aggregate
s for private types), but, consistent with other forms of aggregate
, we do not look at the form of the aggregate
to determine resolution. This can be incompatible in usually unlikely cases, where overloading of a container or private type with a type that was previously allowed in aggregate
s makes an existing call ambiguous. Unfortunately, Ada.Containers.Vectors has a number of such overloadings for Insert, Append, Prepend, and "&", so the problem may appear for any element type of a Vector that allows aggregates. For instance, if My_Vector is an instance of Ada.Containers.Vectors with an element type of Not_Lim as defined above, and V is an object of My_Vector.Vector, then My_Vector.Append (V, (Comp => 123)); will be illegal in Ada 2022 and legal in Ada 2012. This can easily be fixed by qualifying the aggregate
with the correct type. 4.3.1 Record Aggregates
1[In a record_aggregate
, a value is specified for each component of the record or record extension value, using either a named or a positional association.]
Syntax
2record_aggregate
::=
(record_component_association_list
)
3record_component_association_list
::=
record_component_association
{, record_component_association
}
| null record
4/2record_component_association
::=
[component_choice_list
=>] expression
| component_choice_list
=> <>
5/5component_choice_list
::=
component_selector_name
{'|' component_selector_name
}
| others
6A record_component_association
is a named component association if it has a component_choice_list
; otherwise, it is a positional component association. Any positional component associations shall precede any named component associations. If there is a named association with a component_choice_list
of others, it shall come last.
In the record_component_association_list
for a record_aggregate
, if there is only one association, it shall be a named association.
record_component_association_list
in both record_aggregate
and extension_aggregate
. Name Resolution Rules
8/2The expected type for a record_aggregate
shall be a single record type or record extension.
aggregate
is an array_aggregate
or a record_aggregate
. The presence of a with is used to resolve between a record_aggregate
and an extension_aggregate
. For the record_component_association_list
of a record_aggregate
, all components of the composite value defined by the aggregate are needed[; for the association list of an extension_aggregate
, only those components not determined by the ancestor expression or subtype are needed (see 4.3.2).] Each component_selector_name
in a record_component_association
of a record_aggregate
or extension_aggregate
shall denote a needed component [(including possibly a discriminant)]. Each component_selector_name
in a record_component_association
of a record_delta_aggregate
(see 4.3.4) shall denote a nondiscriminant component of the type of the aggregate
.
record_aggregate
, “needed components” includes every component of the composite value, but does not include those in unchosen variant
s (see AI83-309). If there are variant
s, then the value specified for the discriminant that governs them determines which variant
is chosen, and hence which components are needed.known_discriminant_part
, then all of its discriminants are needed in the component association list of an extension aggregate for that type, even if the discriminants have the same names and types as discriminants of the type of the ancestor expression. This is necessary to ensure that the positions in the record_component_association_list
are well defined, and that discriminants that govern variant_part
s can be given by static expressions. record_delta_aggregate
s so that there is no completeness requirement. But that means that we need to ensure that the rules using “needed” doesn't appear to apply to record_delta_aggregate
s, and we also need Legality Rules to prevent giving the same component twice and giving components from two different variants. The expected type for the expression
of a record_component_association
is the type of the associated component(s); the associated component(s) are as follows:
- For a positional association, the component [(including possibly a discriminant)] in the corresponding relative position (in the declarative region of the type), counting only the needed components;
extension_aggregate
, only noninherited components are counted to determine the position.- For a named association with one or more component_
selector_name
s, the named component(s); 14 - For a named association with the reserved word others, all needed components that are not associated with some previous association.
Legality Rules
15If the type of a record_aggregate
is a record extension, then it shall be a descendant of a record type, through one or more record extensions (and no private extensions).
A record_component_association_list
shall be null record only if the list occurs in a record_aggregate
or extension_aggregate
, and there are no components needed for that list .
record_aggregate
for a null record type. Similarly, "(T'(A) with null record)" is an extension_aggregate
for a type defined as a null record extension of T.record_component_association
must necessarily be others => <>, as that is the only record_component_association
that does not require an associated component. For a record_aggregate
or extension_aggregate
, each record_component_association
other than an others choice with a <> shall have at least one associated component, and each needed component shall be associated with exactly one record_component_association
. For a record_delta_aggregate
, each component_selector_name
of each component_choice_list
shall denote a distinct nondiscriminant component of the type of the aggregate.
expression
of the association. Note that some of the rules do not apply to <> associations, as we do not need to resolve anything. We allow others => <> to match no components as this is similar to array aggregates. That means that (others => <>) always represents a default-initialized record or array value. record_component_association
implies that there can be no extra associations for components that don't exist in the composite value, or that are already determined by the ancestor expression or subtype of an extension_aggregate
.If a record_component_association
with an expression
has two or more associated components, all of them shall be of the same type, or all of them shall be of anonymous access types whose subtypes statically match. In addition, Legality Rules are enforced separately for each associated component.
expression
shall be legal for each associated component. Ada 95 omitted this wording, as it was thought that all cases of difference had been eliminated. That probably was true, but Ada 2005 reintroduced cases where the types match but the legality differs. For example:type Rec (D : access Integer) is record
F : access Integer;
end record;
17.h/5begin
declare
X : aliased Integer;
R : Rec := (D | F => X'Access); -- Legal for D, illegal for F
For a record_aggregate
or extension_aggregate
, if a variant_part
P is nested within a variant
V that is not selected by the discriminant value governing the variant_part
enclosing V, then there is no restriction on the discriminant governing P. Otherwise, the value of the discriminant that governs P shall be given by a static expression, or by a nonstatic expression having a constrained static nominal subtype. In this latter case of a nonstatic expression, there shall be exactly one discrete_choice_list
of P that covers each value that belongs to the nominal subtype and satisfies the predicates of the subtype, and there shall be at least one such value.
derived_type_definition
for some ancestor of the type of the aggregate.A record_component_association
for a discriminant without a default_expression
shall have an expression
rather than <>.
A record_component_association
of the record_component_association_list
of a record_delta_aggregate
shall not:
- use the box compound delimiter <> rather than an
expression
; 18.4/5 - have an
expression
of a limited type; 18.5/5 - omit the
component_choice_list
; or
record_delta_aggregate
cannot use positional notation; all choices shall be named choices. - have a
component_choice_list
that is an others choice.
For a record_delta_aggregate
, no two component_selector_name
s shall denote components declared within different variant
s of the same variant_part
.
Dynamic Semantics
19The evaluation of a record_aggregate
consists of the evaluation of the record_component_association_list
.
For the evaluation of a record_component_association_list
, any per-object constraints (see 3.8) for components specified in the association list are elaborated and any expression
s are evaluated and converted to the subtype of the associated component. Any constraint elaborations and expression
evaluations (and conversions) occur in an arbitrary order, except that the expression
for a discriminant is evaluated (and converted) prior to the elaboration of any per-object constraint that depends on it, which in turn occurs prior to the evaluation and conversion of the expression
for the component with the per-object constraint. If the value of a discriminant that governs a selected variant_part
P is given by a nonstatic expression
, and the evaluation of that expression
yields a value that does not belong to the nominal subtype of the expression
, then Constraint_Error is raised.
For a record_component_association
with an expression
, the expression
defines the value for the associated component(s). For a record_component_association
with <>, if the component_declaration
has a default_expression
, that default_expression
defines the value for the associated component(s); otherwise, the associated component(s) are initialized by default as for a stand-alone object of the component subtype (see 3.3.1).
The expression
of a record_component_association
is evaluated (and converted) once for each associated component.
record_aggregate
with positional associations, expressions specifying discriminant values appear first since the known_discriminant_part
is given first in the declaration of the type; they have to be in the same order as in the known_discriminant_part
. Examples
23Example of a record aggregate with positional associations:
(4, July, 1776) -- see 3.8
25Examples of record aggregates with named associations:
(Day => 4, Month => July, Year => 1776)
(Month => July, Day => 4, Year => 1776)
27(Disk, Closed, Track => 5, Cylinder => 12) -- see 3.8.1
(Unit => Disk, Status => Closed, Cylinder => 9, Track => 1)
28/2Examples of component associations with several choices:
(Value => 0, Succ|Pred => new Cell'(0, null, null)) -- see 3.10.1
30-- The allocator is evaluated twice: Succ and Pred designate different cells
30.1/2(Value => 0, Succ|Pred => <>) -- see 3.10.1
30.2/2-- Succ and Pred will be set to null
31Examples of record aggregates for tagged types (see 3.9 and 3.9.1):
Expression'(null record)
Literal'(Value => 0.0)
Painted_Point'(0.0, Pi/2.0, Paint => Red)
Extensions to Ada 83
Wording Changes from Ada 83
Extensions to Ada 95
Wording Changes from Ada 95
Incompatibilities With Ada 2005
variant_part
s was not effectively circular. The change makes a few aggregate
s where a nonstatic discriminant governs an empty variant_part
illegal. However, most Ada implementations already enforce some version of the new rule and already reject these aggregate
s. So it is unlikely that any incompatibility will be noticed in practice. Extensions to Ada 2005
Extensions to Ada 2012
variant_part
in an aggregate
can be nonstatic if the nominal subtype of the discriminant expression is static and all possible values select a single variant
. Wording Changes from Ada 2012
4.3.2 Extension Aggregates
1[An extension_aggregate
specifies a value for a type that is a record extension by specifying a value or subtype for an ancestor of the type, followed by associations for any components not determined by the ancestor_part
.]
Language Design Principles
record_component_association_list
corresponds to exactly what would be needed if there were no ancestor/prefix type. The ancestor_part
determines the value of the ancestor/prefix. Syntax
2extension_aggregate
::=
(ancestor_part
with record_component_association_list
)
3ancestor_part
::=
expression
| subtype_mark
Name Resolution Rules
4/2The expected type for an extension_aggregate
shall be a single type that is a record extension. If the ancestor_part
is an expression
, it is expected to be of any tagged type.
Legality Rules
5/3If the ancestor_part
is a subtype_mark
, it shall denote a specific tagged subtype. If the ancestor_part
is an expression
, it shall not be dynamically tagged. The type of the extension_aggregate
shall be a descendant of the type of the ancestor_part
(the ancestor type), through one or more record extensions (and no private extensions). If the ancestor_part
is a subtype_mark
, the view of the ancestor type from which the type is descended (see 7.3.1) shall not have unknown discriminants.
If the type of the ancestor_part
is limited and at least one component is needed in the record_component_association_list
, then the ancestor_part
shall not have an operative constituent expression (see 4.4) that is a call to a function with an unconstrained result subtype.
qualified_expression
s, and conditional_expression
s are ignored when enforcing this rule. Static Semantics
6For the record_component_association_list
of an extension_aggregate
, the only components needed are those of the composite value defined by the aggregate that are not inherited from the type of the ancestor_part
, plus any inherited discriminants if the ancestor_part
is a subtype_mark
that denotes an unconstrained subtype.
Dynamic Semantics
7For the evaluation of an extension_aggregate
, the record_component_association_list
is evaluated. If the ancestor_part
is an expression
, it is also evaluated; if the ancestor_part
is a subtype_mark
, the components of the value of the aggregate not given by the record_component_association_list
are initialized by default as for an object of the ancestor type. Any implicit initializations or evaluations are performed in an arbitrary order, except that the expression
for a discriminant is evaluated prior to any other evaluation or initialization that depends on it.
If the type of the ancestor_part
has discriminants and the ancestor_part
is not a subtype_mark
that denotes an unconstrained subtype, then a check is made that each discriminant determined by the ancestor_part
has the value specified for a corresponding discriminant, if any, either in the record_component_association_list
, or in the derived_type_definition
for some ancestor of the type of the extension_aggregate
. Constraint_Error is raised if this check fails.
extension_aggregate
are determined by the ancestor_part
, then the record_component_association_list
is required to be simply null record.ancestor_part
is a subtype_mark
, then its type can be abstract. If its type is controlled, then as the last step of evaluating the aggregate, the Initialize procedure of the ancestor type is called, unless the Initialize procedure is abstract (see 7.6). Examples
11Examples of extension aggregates (for types defined in 3.9.1):
Painted_Point'(Point with Red)
(Point'(P) with Paint => Black)
13/5(Expression with Left => new Literal'(Value => 1.2),
Right => new Literal'(Value => 3.4))
Addition'(Binop with null record)
-- presuming Binop is of type Binary_Operation
Extensions to Ada 83
Incompatibilities With Ada 95
expression
. If an aggregate
includes such an expression
, it is illegal in Ada 2005. Such aggregate
s are thought to be rare; the problem can be fixed with a type conversion to the appropriate specific type if it occurs. Wording Changes from Ada 95
extension_aggregate
s are allowed (since all kinds of aggregates can now be limited, see 4.3). Inconsistencies With Ada 2005
extension_aggregate
with an ancestor_part
whose discriminants are constrained and inherited might now raise Constraint_Error if the aggregate
's type is constrained, while it was OK in Ada 2005. In almost all cases, this will make no difference as the constraint will be checked by the immediately following use of the aggregate
, but it is possible to compare such an aggregate for equality; in this case, no exception would be raised by Ada 2005, while Ada 2012 will raise Constraint_Error. This should be very rare, and having the possibility means that the representation of the aggregate type has to be able to support unconstrained values of the type, even if the first subtype is constrained and no such objects can be created any other way. Incompatibilities With Ada 2005
aggregate
s were first introduced in Ada 2005 and are very complex to implement as they must be built-in-place with an unknown size; as such, it is unlikely that they are implemented correctly in existing compilers and thus not often used in existing code.ancestor_part
that is a subtype with unknown discriminants is now explicitly illegal. Such a subtype should not be used to declare an object, and the ancestor_part
acts like an object. The Ada 95 rules did not disallow such cases, so it is possible that code exists that uses such an ancestor, but this should be rare. Wording Changes from Ada 2012
4.3.3 Array Aggregates
1[In an array_aggregate
, a value is specified for each component of an array, either positionally or by its index.] For a positional_array_aggregate
, the components are given in increasing-index order, with a final others, if any, representing any remaining components. For a named_array_aggregate
, the components are identified by the values covered by the discrete_choice
s.
Language Design Principles
discrete_choice_list
s defined in 3.8.1, “Variant Parts and Discrete Choices”. For example, the requirements that others come last and stand alone are found there. Syntax
2/5array_aggregate
::=
positional_array_aggregate
| null_array_aggregate
| named_array_aggregate
3/5positional_array_aggregate
::=
(expression
, expression
{, expression
})
| (expression
{, expression
}, others => expression
)
| (expression
{, expression
}, others => <>)
| '[' expression
{, expression
}[, others => expression
] ']'
| '[' expression
{, expression
}, others => <> ']'
3.1/5null_array_aggregate
::=
'[' ']'
4/5named_array_aggregate
::=
(array_component_association_list
)
| '[' array_component_association_list
']'
4.1/5array_component_association_list
::=
array_component_association
{, array_component_association
}
5/5array_component_association
::=
discrete_choice_list
=> expression
| discrete_choice_list
=> <>
| iterated_component_association
5.1/5iterated_component_association
::=
for defining_identifier
in discrete_choice_list
=> expression
| for iterator_specification
=> expression
6An n-dimensional array_aggregate
is one that is written as n levels of nested array_aggregate
s (or at the bottom level, equivalent string_literal
s). For the multidimensional case (n >= 2) the array_aggregate
s (or equivalent string_literal
s) at the n–1 lower levels are called subaggregates of the enclosing n-dimensional array_aggregate
. The expression
s of the bottom level subaggregates (or of the array_aggregate
itself if one-dimensional) are called the array component expressions of the enclosing n-dimensional array_aggregate
.
array_aggregate
applies to subaggregates as well as aggregate
s that have a type. positional_array_aggregate
or as the discrete_choice
of the discrete_choice_list
in an array_component_association
. The defining_identifier
of an iterated_component_association
declares an index parameter, an object of the corresponding index type.
Name Resolution Rules
7/2The expected type for an array_aggregate
(that is not a subaggregate) shall be a single array type. The component type of this array type is the expected type for each array component expression of the array_aggregate
.
aggregate
. The above rule requiring a single array type (and similar ones for record and extension aggregates) resolves which kind of aggregate you have. The expected type for each discrete_choice
in any discrete_choice_list
of a named_array_aggregate
is the type of the corresponding index; the corresponding index for an array_aggregate
that is not a subaggregate is the first index of its type; for an (n–m)-dimensional subaggregate within an array_aggregate
of an n-dimensional type, the corresponding index is the index in position m+1.
Legality Rules
9/5An array_aggregate
of an n-dimensional array type shall be written as an n-dimensional array_aggregate
, or as a null_array_aggregate
.
array_aggregate
[(including a subaggregate)], where m >= 2, each of the expression
s has to be an (m–1)-dimensional subaggregate. An others choice is allowed for an array_aggregate
only if an applicable index constraint applies to the array_aggregate
. [An applicable index constraint is a constraint provided by certain contexts that can be used to determine the bounds of the array value specified by an array_aggregate
.] Each of the following contexts (and none other) defines an applicable index constraint:
- For an
explicit_actual_parameter
, anexplicit_generic_actual_parameter
, theexpression
of a return statement, the return expression of an expression function, the initialization expression in anobject_declaration
, or adefault_expression
[(for a parameter or a component)], when the nominal subtype of the corresponding formal parameter, generic formal parameter, function return object, expression function return object, object, or component is a constrained array subtype, the applicable index constraint is the constraint of the subtype; 12 - For the
expression
of anassignment_statement
where thename
denotes an array variable, the applicable index constraint is the constraint of the array variable;
- For the operand of a
qualified_expression
whosesubtype_mark
denotes a constrained array subtype, the applicable index constraint is the constraint of the subtype; 14 - For a component
expression
in anaggregate
, if the component's nominal subtype is a constrained array subtype, the applicable index constraint is the constraint of the subtype;
array_aggregate
with others is being used within a larger aggregate. - For the base_
expression
of adelta_aggregate
, if the nominal subtype of thedelta_aggregate
is a constrained array subtype, the applicable index constraint is the constraint of the subtype; 15/3 - For a parenthesized
expression
, the applicable index constraint is that, if any, defined for theexpression
;
expression
becomes illegal if parenthesized. - For a
conditional_expression
(see 4.5.7), the applicable index constraint for each dependent_expression
is that, if any, defined for theconditional_expression
; 15.2/5 - For a
declare_expression
(see 4.5.9), the applicable index constraint for the body_expression
is that, if any, defined for thedeclare_expression
.
The applicable index constraint applies to an array_aggregate
that appears in such a context, as well as to any subaggregates thereof. In the case of an explicit_actual_parameter
(or default_expression
) for a call on a generic formal subprogram, no applicable index constraint is defined.
The discrete_choice_list
of an array_component_association
(including an iterated_component_association
) is allowed to have a discrete_choice
that is a nonstatic choice_expression
or that is a subtype_indication
or range
that defines a nonstatic or null range, only if it is the single discrete_choice
of its discrete_choice_list
, and either there is only one array_component_association
in the enclosing array_component_association_list
or the enclosing aggregate
is an array_delta_aggregate
[, not an array_aggregate
] .
array_delta_aggregate
s, but only one dynamic choice per association even in that case. Either all or none of the array_component_association
s of an array_component_association_list
shall be iterated_component_association
s with an iterator_specification
.
In a named_array_aggregate
where all discrete_choice
s are static, no two discrete_choice
s are allowed to cover the same value (see 3.8.1); if there is no others choice, the discrete_choice
s taken together shall exactly cover a contiguous sequence of values of the corresponding index type.
discrete_choice
; a single choice has to represent a contiguous range (a subtype_mark
with a static predicate might represent a discontiguous set of values). If the (single) choice is a dynamic subtype, we don't need to make this check as no predicates are allowed (see 3.2.4) and thus the range has to be contiguous. A bottom level subaggregate of a multidimensional array_aggregate
of a given array type is allowed to be a string_literal
only if the component type of the array type is a character type; each character of such a string_literal
shall correspond to a defining_character_literal
of the component type.
Static Semantics
20A subaggregate that is a string_literal
is equivalent to one that is a positional_array_aggregate
of the same length, with each expression
being the character_literal
for the corresponding character of the string_literal
.
positional_array_aggregate
. The subtype (and nominal subtype) of an index parameter is the corresponding index subtype.
Dynamic Semantics
20.2/5For an array_aggregate
that contains only array_component_association
s that are iterated_component_association
s with iterator_specification
s, evaluation proceeds in two steps:
a)
- Each
iterator_specification
is elaborated (in an arbitrary order) and an iteration is performed solely to determine a maximum count for the number of values produced by the iteration; all of these counts are combined to determine the overall length of the array, and ultimately the limits on the bounds of the array (defined below); 20.4/5
b)- A second iteration is performed for each of the
iterator_specification
s, in the order given in theaggregate
, and for each value conditionally produced by the iteration (see 5.5 and 5.5.2), the associatedexpression
is evaluated, its value is converted to the component subtype of the array type, and used to define the value of the next component of the array starting at the low bound and proceeding sequentially toward the high bound. A check is made that the second iteration results in an array length no greater than the maximum determined by the first iteration; Constraint_Error is raised if this check fails.
The evaluation of any other array_aggregate
of a given array type proceeds in two steps:
a)
- Any
discrete_choice
s of this aggregate and of its subaggregates are evaluated in an arbitrary order, and converted to the corresponding index type; 23
b)- The array component expressions of the aggregate are evaluated in an arbitrary order and their values are converted to the component subtype of the array type; an array component expression is evaluated once for each associated component.
Each expression
in an array_component_association
defines the value for the associated component(s). For an array_component_association
with <>, the associated component(s) are initialized to the Default_Component_Value of the array type if this aspect has been specified for the array type; otherwise, they are initialized by default as for a stand-alone object of the component subtype (see 3.3.1).
During an evaluation of the expression
of an iterated_component_association
with a discrete_choice_list
, the value of the corresponding index parameter is that of the corresponding index of the corresponding array component. During an evaluation of the expression
of an iterated_component_association
with an iterator_specification
, the value of the loop parameter of the iterator_specification
is the value produced by the iteration (as described in 5.5.2).
iterated_component_association
can take on its values in an arbitrary order. This is different from other constructs, such as a loop_statement
. In contrast, a loop parameter of an iterated_component_association
takes its values in the order defined by the iteration, the same as a loop_statement
. The bounds of the index range of an array_aggregate
[(including a subaggregate)] are determined as follows:
- For an
array_aggregate
with an others choice, the bounds are those of the corresponding index range from the applicable index constraint; 26 - For a
positional_array_aggregate
[(or equivalentstring_literal
)] without an others choice, the lower bound is that of the corresponding index range in the applicable index constraint, if defined, or that of the corresponding index subtype, if not; in either case, the upper bound is determined from the lower bound and the number ofexpression
s [(or the length of thestring_literal
)]; 26.1/5 - For a
null_array_aggregate
, bounds for each dimension are determined as for apositional_array_aggregate
without an others choice that has no expressions for each dimension;
null_array_aggregate
; we could've combined the single-dimension case with the positional_array_aggregate
rule. - For a
named_array_aggregate
containing onlyiterated_component_association
s with aniterator_specification
, the lower bound is determined as for apositional_array_aggregate
without an others choice, and the upper bound is determined from the lower bound and the total number of values produced by the second set of iterations; 27/5 - For any other
named_array_aggregate
without an others choice, the bounds are determined by the smallest and largest index values covered by anydiscrete_choice_list
.
aggregate
s that each component's value has to be specified exactly once. For an array_aggregate
, a check is made that the index range defined by its bounds is compatible with the corresponding index subtype.
For an array_aggregate
with an others choice, a check is made that no expression
or <> is specified for an index value outside the bounds determined by the applicable index constraint.
For a multidimensional array_aggregate
, a check is made that all subaggregates that correspond to the same index have the same bounds.
The exception Constraint_Error is raised if any of the above checks fail.
Implementation Permissions
32/5When evaluating iterated_component_association
s for an array_aggregate
that contains only iterated_component_association
s with iterator_specification
s, the first step of evaluating an iterated_component_association
can be omitted if the implementation can determine the maximum number of values by some other means.
array_aggregate
delimited by parentheses, positional notation can only be used with two or more expression
s; a single expression
in parentheses is interpreted as a parenthesized expression. An array_aggregate
delimited by square brackets can be used to specify an array with a single component.Examples
35Examples of array aggregates with positional associations:
(7, 9, 5, 1, 3, 2, 4, 8, 6, 0)
Table'(5, 8, 4, 1, others => 0) -- see 3.6
37Examples of array aggregates with named associations:
(1 .. 5 => (1 .. 8 => 0.0)) -- two-dimensional
[ 1 .. N => new Cell] -- N new cells, in particular for N = 0
39/5Table'(2 | 4 | 10 => 1, others => 0)
Schedule'(Mon .. Fri => True, others => False) -- see 3.6
Schedule'[ Wed | Sun => False, others => True]
Vector'(1 => 2.5) -- single-component vector
40Examples of two-dimensional array aggregates:
-- Three aggregates for the same value of subtype Matrix(1..2,1..3) (see 3.6):
42/5((1.1, 1.2, 1.3), (2.1, 2.2, 2.3))
(1 => [ 1.1, 1.2, 1.3] , 2 => [ 2.1, 2.2, 2.3] )
[ 1 => (1 => 1.1, 2 => 1.2, 3 => 1.3), 2 => (1 => 2.1, 2 => 2.2, 3 => 2.3)]
43Examples of aggregates as initial values:
A : Table := (7, 9, 5, 1, 3, 2, 4, 8, 6, 0); -- A(1)=7, A(10)=0
B : Table := (2 | 4 | 10 => 1, others => 0); -- B(1)=0, B(10)=1
C : constant Matrix := (1 .. 5 => (1 .. 8 => 0.0)); -- C'Last(1)=5, C'Last(2)=8
45D : Bit_Vector(M .. N) := (M .. N => True); -- see 3.6
E : Bit_Vector(M .. N) := (others => True);
F : String(1 .. 1) := (1 => 'F'); -- a one component aggregate: same as "F"
46/5G : constant Matrix :=
(for I in 1 .. 4 =>
(for J in 1 .. 4 =>
(if I=J then 1.0 else 0.0))); -- Identity matrix
47/5Empty_Matrix : constant Matrix := []; -- A matrix without elements
48/2Example of an array aggregate with defaulted others choice and with an applicable index constraint provided by an enclosing record aggregate:
Buffer'(Size => 50, Pos => 1, Value => ('x', others => <>)) -- see 3.7
Incompatibilities With Ada 83
subtype S3 is String (1 .. 3);
...
generic
with function F (The_S3 : in S3) return Integer;
package Gp is
I : constant Integer := F ((1 => '!', others => '?'));
-- The aggregate is legal in Ada 83, illegal in Ada 95.
end Gp;
Extensions to Ada 83
Wording Changes from Ada 83
Extensions to Ada 95
Wording Changes from Ada 95
aggregate
s to use the subtype of the return object of a function, rather than the result subtype, because they can be different for an extended_return_statement
, and we want to use the subtype that's explicitly in the code at the point of the expression
. Inconsistencies With Ada 2005
expression
s and <>s. As <> was a new feature in Ada 2005, there should be little existing code that depends on a <> component that is specified outside of the array (and that is nonsense anyway, that a compiler is likely to detect even without an explicit language rule disallowing it). Wording Changes from Ada 2005
conditional_expression
s (which are new). Inconsistencies With Ada 2012
Extensions to Ada 2012
iterated_component_association
is new (more than 25 years after it was originally proposed). It has been extended to allow container iterators as well as the basic index iterators.array_aggregate
can be surrounded by brackets rather than parentheses. This allows consistent writing of zero- and one-component positional array aggregates, and is consistent with the syntax for writing container aggregates.Wording Changes from Ada 2012
declare_expression
s (which are new). This allows others in array aggregates inside of declare_expression
s. 4.3.4 Delta Aggregates
1/5Evaluating a (record or array) delta aggregate yields a composite value that starts with a copy of another value of the same type and then assigns to some (but typically not all) components of the copy.
Syntax
2/5delta_aggregate
::=
record_delta_aggregate
| array_delta_aggregate
3/5record_delta_aggregate
::=
(base_expression
with delta record_component_association_list
)
4/5array_delta_aggregate
::=
(base_expression
with delta array_component_association_list
)
| '[' base_expression
with delta array_component_association_list
']'
Name Resolution Rules
5/5The expected type for a record_delta_aggregate
shall be a single descendant of a record type or record extension.
The expected type for an array_delta_aggregate
shall be a single array type.
The expected type for the base_expression
of any delta_aggregate
is the type of the enclosing delta_aggregate
.
[The Name Resolution Rules and Legality Rules for each record_component_association
of a record_delta_aggregate
are as defined in 4.3.1.]
For an array_delta_aggregate
, the expected type for each discrete_choice
in an array_component_association
is the index type of the type of the delta_aggregate
.
The expected type of the expression
in an array_component_association
is defined as for an array_component_association
occurring within an array_aggregate
of the type of the delta_aggregate
.
Legality Rules
11/5For an array_delta_aggregate
, the array_component_association
shall not use the box symbol <>, and the discrete_choice
shall not be others.
For an array_delta_aggregate
, the dimensionality of the type of the delta_aggregate
shall be 1.
For an array_delta_aggregate
, the base_expression
and each expression
in every array_component_association
shall be of a nonlimited type.
expression
of a record_delta_aggregate
may be of a limited type (for example a record with limited components), as it is not restricted. A rule in 4.3.1 ensures that we do not assign to a limited component. We do not allow any part of an array_delta_aggregate
to be of a limited type, even the base_expression
, as this is a useless construct (you would not be able to update anything because the components necessarily are also limited except in pathological cases). Dynamic Semantics
14/5The evaluation of a delta_aggregate
begins with the evaluation of the base_expression
of the delta_aggregate
; then that value is used to create and initialize the anonymous object of the aggregate
. The bounds of the anonymous object of an array_delta_aggregate
and the discriminants (if any) of the anonymous object of a record_delta_aggregate
are those of the base_expression
. If a record_delta_aggregate
is of a specific tagged type, its tag is that of the specific type; if it is of a class-wide type, its tag is that of the base_expression
.
expression
might have are not used to initialize the anonymous object, which is critical if the aggregate is required to be built-in-place. delta_aggregate
begins its life as a variable, not a constant (3.3 notwithstanding). This must be the case because the object is initialized and then subsequently modified. After evaluation of the delta_aggregate
is complete, the object is a constant object. This is similar to the way that an extended return statement can provide a variable view of an object that will eventually be a constant object after the function returns its result. For a record_delta_aggregate
, for each component associated with each record_component_association
(in an unspecified order):
- if the associated component belongs to a
variant
, a check is made that the values of the discriminants are such that the anonymous object has this component. The exception Constraint_Error is raised if this check fails. 17/5 - the
expression
of therecord_component_association
is evaluated, converted to the nominal subtype of the associated component, and assigned to the component of the anonymous object.
For an array_delta_aggregate
, for each discrete_choice
of each array_component_association
(in the order given in the enclosing discrete_choice_list
and array_component_association_list
, respectively) the discrete_choice
is evaluated; for each represented index value (in ascending order, if the discrete_choice
represents a range):
- the index value is converted to the index type of the array type.
- a check is made that the index value belongs to the index range of the anonymous object of the
aggregate
; Constraint_Error is raised if this check fails. 21/5 - the component
expression
is evaluated, converted to the array component subtype, and assigned to the component of the anonymous object identified by the index value.
aggregate
s, an array_delta_aggregate
is evaluated in the order that it is written. This is necessary to get deterministic behavior, as (unlike other aggregate
s, including record_delta_aggregate
s) there is no requirement that the specified components be distinct. As such, the order requirement ensures that every array_delta_aggregate
has a well-defined result, even if the same component is specified multiple times. Examples
22/5Examples of use of delta aggregates in a postcondition:
procedure Twelfth (D : in out Date) -- see 3.8 for type Date
with Post => D = (D'Old with delta Day => 12);
24/5procedure The_Answer (V : in out Vector;
A, B : in Integer) -- see 3.6 for type Vector
with Post => V = (V'Old with delta A .. B => 42.0, V'First => 0.0);
25/5Examples where the base expression is nontrivial:
New_Cell : Cell := (Min_Cell (Head) with delta Value => 42);
-- see 3.10.1 for Cell and Head; 6.1 for Min_Cell
27/5A1 : Vector := ((0 => 1.0, 1 => 2.0, 2 => 3.0)
with delta Integer(Random * 2.0) => 14.2);
-- see 3.6 for declaration of type Vector
-- see 6.1 for declaration of Random
28/5Tomorrow := ((Yesterday with delta Day => 12)
with delta Month => April); -- see 3.8
29/5Example where the base expression is class-wide:
function Translate (P : Point'Class; X, Y : Real) return Point'Class is
(P with delta X => P.X + X,
Y => P.Y + Y); -- see 3.9 for declaration of type Point
Extensions to Ada 2012
4.3.5 Container Aggregates
1/5In a container_aggregate
, values are specified for elements of a container; for a positional_container_aggregate
, the elements are given sequentially; for a named_container_aggregate
, the elements are specified by a sequence of key/value pairs, or using an iterator. The Aggregate aspect of the type of the aggregate
determines how the elements are combined to form the container.
For a type other than an array type, the following type-related operational aspect may be specified:
Aggregate
- This aspect is an
aggregate
of the form:
(Empty => name
[,
Add_Named => procedure_name
][,
Add_Unnamed => procedure_name
][,
New_Indexed => function_name
,
Assign_Indexed => procedure_name
])
- The type for which this aspect is specified is known as the container type of the Aggregate aspect. A procedure_
name
shall be specified for at least one of Add_Named, Add_Unnamed, or Assign_Indexed. If Add_Named is specified, neither Add_Unnamed nor Assign_Indexed shall be specified. Either both or neither of New_Indexed and Assign_Indexed shall be specified.
Name Resolution Rules
7/5The name
specified for Empty for an Aggregate aspect shall denote a constant of the container type, or denote exactly one function with a result type of the container type that has no parameters, or that has one in parameter of a signed integer type.
The procedure_name
specified for Add_Unnamed for an Aggregate aspect shall denote exactly one procedure that has two parameters, the first an in out parameter of the container type, and the second an in parameter of some nonlimited type, called the element type of the container type.
The function_name
specified for New_Indexed for an Aggregate aspect shall denote exactly one function with a result type of the container type, and two parameters of the same discrete type, with that type being the key type of the container type.
The procedure_name
specified for Add_Named or Assign_Indexed for an Aggregate aspect shall denote exactly one procedure that has three parameters, the first an in out parameter of the container type, the second an in parameter of a nonlimited type (the key type of the container type), and the third, an in parameter of a nonlimited type that is called the element type of the container type.
Legality Rules
11/5If the container type of an Aggregate aspect is a private type, the full type of the container type shall not be an array type. If the container type is limited, the name specified for Empty shall denote a function rather than a constant object.
For an Aggregate aspect, the key type of Assign_Indexed shall be the same type as that of the parameters of New_Indexed. Additionally, if both Add_Unnamed and Assign_Indexed are specified, the final parameters shall be of the same type — the element type of the container type.
Static Semantics
13/5The Aggregate aspect is nonoverridable (see 13.1.1).
Syntax
14/5container_aggregate
::=
null_container_aggregate
| positional_container_aggregate
| named_container_aggregate
15/5null_container_aggregate
::=
'[' ']'
16/5positional_container_aggregate
::=
'[' expression
{, expression
} ']'
17/5named_container_aggregate
::=
'[' container_element_association_list
']'
aggregate
s, container aggregates have to be surrounded with brackets rather than parentheses. Using brackets allows writing zero- and one-element positional aggregate
s. (Were we to use parentheses, a one-element positional aggregate would look the same as and would always be interpreted as a parenthesized expression.) Unlike the case for arrays, where it is always possible to give bounds to work around this gap, such an aggregate
could not be written at all for a sequence type (such as a list) where there is no index or key to use. container_element_association_list
::=
container_element_association
{, container_element_association
}
19/5container_element_association
::=
key_choice_list
=> expression
| key_choice_list
=> <>
| iterated_element_association
20/5key_choice_list
::=
key_choice
{'|' key_choice
}
21/5key_choice
::=
key_expression
| discrete_range
22/5iterated_element_association
::=
for loop_parameter_specification
[ use key_expression
] => expression
| for iterator_specification
[ use key_expression
] => expression
Name Resolution Rules
23/5The expected type for a container_aggregate
shall be a single type for which the Aggregate aspect has been specified. The expected type for each expression
of a container_aggregate
is the element type of the expected type.
The expected type for a key_expression
, or a discrete_range
of a key_choice
, is the key type of the expected type of the aggregate
.
Legality Rules
25/5The expected type for a positional_container_aggregate
shall have an Aggregate aspect that includes a specification for an Add_Unnamed procedure or an Assign_Indexed procedure. The expected type for a named_container_aggregate
that contains one or more iterated_element_association
s with a key_expression
shall have an Aggregate aspect that includes a specification for the Add_Named procedure. The expected type for a named_container_aggregate
that contains one or more key_choice_list
s shall have an Aggregate aspect that includes a specification for the Add_Named or Assign_Indexed procedure. [A null_container_aggregate
can be of any type with an Aggregate aspect.]
A non-null container aggregate is called an indexed aggregate if the expected type T of the aggregate specifies an Assign_Indexed procedure in its Aggregate aspect, and either there is no Add_Unnamed procedure specified for the type, or the aggregate is a named_container_aggregate
with a container_element_association
that contains a key_choice_list
or a loop_parameter_specification
. The key type of an indexed aggregate is also called the index type of the aggregate.
A container_element_association
with a <> rather than an expression
, or with a key_choice
that is a discrete_range
, is permitted only in an indexed aggregate.
iterated_element_association
. For an iterated_element_association
without a key_expression
, if the aggregate
is an indexed aggregate or the expected type of the aggregate
specifies an Add_Named 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 the aggregate
.
expression
in an iterated_element_association
, it determines the key of each added key/value pair, rather than the loop parameter. But if there is no key_expression
, the loop parameter itself is used as the key. For a named_container_aggregate
that is an indexed aggregate, all container_element_association
s shall contain either a key_choice_list
, or a loop_parameter_specification
without a key_expression
or iterator_filter
. Furthermore, for such an aggregate, either:
- all
key_choice
s shall be static expressions or static ranges, and everyloop_parameter_specification
shall have adiscrete_subtype_definition
that defines a non-null static range, and the set of values of the index type covered by thekey_choice
s and thediscrete_subtype_definition
s shall form a contiguous range of values with no duplications; or 31/5 - there shall be exactly one
container_element_association
, and if it has akey_choice_list
, the list shall have exactly onekey_choice
.
named_array_aggregate
s, without others. Dynamic Semantics
32/5The evaluation of a container_aggregate
starts by creating an anonymous 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 lower and upper bound of theaggregate
, and are determined as follows: 34/5 - if the
aggregate
is apositional_container_aggregate
, the lower bound is the low bound of the subtype of the key parameter of the Add_Indexed procedure, and the upper bound has a position number that is the sum of the position number of the lower bound and one less than the number ofexpression
s in theaggregate
; 35/5 - if the
aggregate
is anamed_container_aggregate
, the lower bound is the lowest value covered by akey_choice_list
or is the low bound of a range defined by adiscrete_subtype_definition
of aloop_parameter_specification
; the upper bound is the highest value covered by akey_choice_list
or is the high bound of a range defined by adiscrete_subtype_definition
of aloop_parameter_specification
. 36/5 - 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: 37/5 - for a
null_container_aggregate
, the value zero; 38/5 - for a
positional_container_aggregate
, the number ofexpression
s; 39/5 - for a
named_container_aggregate
without aniterated_element_association
, the number of key_expression
s; 40/5 - for a
named_container_aggregate
where everyiterated_element_association
contains aloop_parameter_specification
, the total number of elements specified by all of thecontainer_element_association
s; 41/5 - otherwise, to an implementation-defined value.
aggregate
, if one is available. If not, it is suggested to use the default value for the parameter if one exists, and zero otherwise. container_aggregate
s.The evaluation then proceeds as follows:
- for a
null_container_aggregate
, the anonymous object A is the result; 44/5 - for a
positional_container_aggregate
of a type with a specified Add_Unnamed procedure, eachexpression
is evaluated in an arbitrary order, and the Add_Unnamed procedure is invoked in sequence with the anonymous object A as the first parameter and the result of evaluating eachexpression
as the second parameter, in the order of theexpression
s; 45/5 - for a
positional_container_aggregate
that is an indexed aggregate, eachexpression
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 successiveexpression
, and the result of evaluating eachexpression
as the third parameter; 46/5 - for a
named_container_aggregate
for a type with an Add_Named procedure in its Aggregate aspect, thecontainer_element_association
s are evaluated in an arbitrary order: 47/5 - for a
container_element_association
with akey_choice_list
, for eachkey_choice
of the list in an arbitrary order, thekey_choice
is evaluated as is theexpression
of thecontainer_element_association
(in an arbitrary order), and the Add_Named procedure is invoked once for each value covered by thekey_choice
, with the anonymous object A as the first parameter, the value from thekey_choice
as the second parameter, and the result of evaluating theexpression
as the third parameter; 48/5 - for a
container_element_association
with aniterated_element_association
, first theiterated_element_association
is elaborated, then an iteration is performed, and for each value conditionally produced by the iteration (see 5.5 and 5.5.2) the Add_Named procedure is invoked with the anonymous object A as the first parameter, the result of evaluating theexpression
as the third parameter, and: 49/5 - if there is a key_
expression
, the result of evaluating the key_expression
as the second parameter; 50/5 - otherwise, with the loop parameter as the second parameter;
- 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 instead of Add_Named; in the case of acontainer_element_association
with a <> rather than anexpression
, the corresponding call on Assign_Indexed is not performed, leaving the component as it was upon return from the New_Indexed function; 52/5 - for any other
named_container_aggregate
, thecontainer_element_association
s (which are necessarilyiterated_element_association
s) are evaluated in the order given; each such evaluation comprises two steps:
a)
- the
iterated_element_association
is elaborated; 54/5
b)- an iteration is performed, and for each value conditionally produced by the iteration (see 5.5 and 5.5.2) the Add_Unnamed procedure is invoked, with the anonymous object A as the first parameter and the result of evaluating the
expression
as the second parameter.
expression
of the iterated_element_association
. Examples
55/5Examples of specifying the Aggregate aspect for a Set_Type, a Map_Type, and a Vector_Type:
-- Set_Type is a set-like container type.
type Set_Type is private
with Aggregate => (Empty => Empty_Set,
Add_Unnamed => Include);
function Empty_Set return Set_Type;
57/5subtype Small_Int is Integer range -1000..1000;
58/5procedure Include (S : in out Set_Type; N : in Small_Int);
59/5-- Map_Type is a map-like container type.
type Map_Type is private
with Aggregate => (Empty => Empty_Map,
Add_Named => Add_To_Map);
60/5
procedure Add_To_Map (M : in out Map_Type;
Key : in Integer;
Value : in String);
61/5Empty_Map : constant Map_Type;
62/5-- Vector_Type is an extensible array-like container type.
type Vector_Type is private
with Aggregate => (Empty => Empty_Vector,
Add_Unnamed => Append_One,
New_Indexed => New_Vector,
Assign_Indexed => Assign_Element);
63/5function Empty_Vector (Capacity : Integer := 0) return Vector_Type;
64/5procedure Append_One (V : in out Vector_Type; New_Item : in String);
65/5procedure Assign_Element (V : in out Vector_Type;
Index : in Positive;
Item : in String);
66/5function New_Vector (First, Last : Positive) return Vector_Type
with Pre => First = Positive'First;
-- Vectors are always indexed starting at the
-- lower bound of their index subtype.
67/5-- Private part not shown.
68/5Examples of container aggregates for Set_Type, Map_Type, and Vector_Type:
-- Example aggregates using Set_Type.
S : Set_Type;
70/5-- Assign the empty set to S:
S := [];
71/5-- Is equivalent to:
S := Empty_Set;
72/5-- A positional set aggregate:
S := [1, 2];
73/5-- Is equivalent to:
S := Empty_Set;
Include (S, 1);
Include (S, 2);
74/5-- A set aggregate with an iterated_element_association:
S := [for Item in 1 .. 5 => Item * 2];
75/5-- Is equivalent to:
S := Empty_Set;
for Item in 1 .. 5 loop
Include (S, Item * 2);
end loop;
76/5-- A set aggregate consisting of two iterated_element_associations:
S := [for Item in 1 .. 5 => Item,
for Item in 1 .. 5 => -Item];
77/5-- Is equivalent (assuming set semantics) to:
S := Empty_Set;
for Item in 1 .. 5 loop
Include (S, Item);
end loop;
for Item in -5 .. -1 loop
Include (S, Item);
end loop;
78/5-- Example aggregates using Map_Type.
M : Map_Type;
79/5-- A simple named map aggregate:
M := [12 => "house", 14 => "beige"];
80/5-- Is equivalent to:
M := Empty_Map;
Add_To_Map (M, 12, "house");
Add_To_Map (M, 14, "beige");
81/5-- Define a table of pairs:
type Pair is record
Key : Integer;
Value : access constant String;
end record;
82/5Table : constant array(Positive range <>) of Pair :=
[(Key => 33, Value => new String'("a nice string")),
(Key => 44, Value => new String'("an even better string"))];
83/5-- A map aggregate using an iterated_element_association
-- and a key_expression, built from from a table of key/value pairs:
M := [for P of Table use P.Key => P.Value.all];
84/5-- Is equivalent to:
M := Empty_Map;
for P of Table loop
Add_To_Map (M, P.Key, P.Value.all);
end loop;
85/5-- Create an image table for an array of integers:
Keys : constant array(Positive range <>) of Integer := [2, 3, 5, 7, 11];
86/5-- A map aggregate where the values produced by the
-- iterated_element_association are of the same type as the key
-- (hence a separate key_expression is unnecessary):
M := [for Key of Keys => Integer'Image (Key)];
87/5-- Is equivalent to:
M := Empty_Map;
for Key of Keys loop
Add_To_Map (M, Key, Integer'Image (Key));
end loop;
88/5-- Example aggregates using Vector_Type.
V : Vector_Type;
89/5-- A positional vector aggregate:
V := ["abc", "def"];
90/5-- Is equivalent to:
V := Empty_Vector (2);
Append_One (V, "abc");
Append_One (V, "def");
91/5-- An indexed vector aggregate:
V := [1 => "this", 2 => "is", 3 => "a", 4 => "test"];
92/5-- 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");