In this example, USA has three parts (called "fields"): USA.Day, USA.Month,
and USA.Year. The fields of a record can be of any type, including other
records. Here USA.Day is of type Integer, USA.Month is of type Month_Type, and
USA.Year is of type Integer. The fields of USA may be referenced separately:

USA.Day :=4;
USA.Month := Jul;
USA.Year :=1776;

However, USA can also be referenced as one object. For example, we could have
assigned all three fields in one statement: USA := (4, Jul, 1776);. Here the
object on the left is of type Date, and the object on the right is called an
aggregate. The aggregate fits the type Date because it contains an Integer, a
Month_Type, and another Integer. This aggregate is said to use positional
notation because its three parts appear in the same order as the three parts of
the record definition: first Day, then Month, then Year.

We can specify the parts of an aggregate in any order if we use named notation:USA := (Month => Jul, Day => 4, Year => 1776);. (The symbol => is read "arrow"
and may not contain a space.) Using named notation often improves program
readability, especially if the names of the fields are well chosen.

We can switch from positional to named notation in an aggregate. But once we
use named notation, the compiler loses track of position, so we can't switch
back to positional. For example, the following is legal:

USA := (4, Year =>1776, Month => Jul);

But the following is illegal because positional notation can't follow named:

USA := (4, Year =>1776, Jul);-- illegal

Record discriminants, record variants, and tagged records will be discussed in
the section on More Records and Types.

No, this statement is legal, because D3 and D2 both have the same type: Date.
An entire record can be assigned with one statement.

Arrays

To declare an array in Ada, we specify the type and range of the subscript,
followed by the type of the elements of the array. The subscript can have any
discrete type (integer or enumeration), and the elements of the array can be of
any type at all, including records and other arrays. There are three ways to
declare an array in Ada. Here are three examples of the most direct, but least
flexible, way (types Rainbow_Color and Date must be defined earlier):

A :array(Rainbow_Color range Orange .. Blue)of Date;-- A four-element array, each element of which is a record-- with three parts. The allowable subscripts are Orange,-- Yellow, Green, and Blue. Here A(Yellow) is of type Date,-- and A(Yellow).Year is of type Integer.
B :array(Integerrange-10..10)ofInteger;-- An array of 21 Integers, with Integer subscripts.
C :array(0..30)ofFloat;-- Here (0 .. 30) is understood to mean-- (Integer range 0 .. 30), and we have an array of 31-- Floats, with Integer subscripts.

A subscript can be an expression; if I is an Integer, we can write C(2*I). If
a subscript is out-of-range (for example, A(Red) or C(-32)), the program will
raise a Constraint_Error.

This direct method of declaring arrays is usually used to create single arrays
for table lookup, etc., where there's no need to have several arrays of the
same type. A better way to declare an array is to specify a type name for the
array itself. Then several objects can be declared to have that same type.
For example,

Here D, E, and F are all of type Vector100, so we can write D := E; and assign
the entire array with one statement. Similarly, we can write G := H;, but not
G := F;, because G and F have different types.

An even more flexible way to declare arrays is to leave the range of the
subscript unspecified with the box symbol, <>, specifying the range when
declaring the objects. For example,

There are two errors to avoid when declaring arrays in this way. One is to
declare a type with the box symbol for the range of the subscript, and then
fail to specify the range when declaring a variable:

type Vector is array(Integerrange<>)ofFloat;
D1 : Vector;-- illegal

This error is called unconstrained array. Unconstrained arrays are legal in
formal parameters ("dummy arguments") of procedures and functions, and a
function can return an unconstrained array type. (We'll learn about these
things later.) But an unconstrained array is illegal when declaring a
variable, because the compiler needs to know the range of the subscript.

In Ada 95, we may constrain the variable array by initializing it:

D1 : Vector := (2.3,4.5,4.0);-- legal in Ada 95 only

Here the compiler assumes the range of the subscript to be 1 .. 3. In Ada 83,
however, we must specify the subscript range of a variable explicitly:

D1 : Vector(1..3) := (2.3,4.5,4.0);-- legal

In both Ada 83 and Ada 95, a constant array, which must be initialized, is
automatically constrained. Therefore, the following is legal in both Ada 83
and Ada 95, and the compiler will assume the subscript range to be 1 .. 3:

D1 :constant Vector := (2.3,4.5,4.0);-- legal

The other error to avoid when declaring arrays in this way is to specify the
range of the subscript twice: once when declaring the type and once when
declaring the object:

If others follows named notation, it's best to qualify the aggregate with the
type name. Here W(10) = 1.3, W(15) = -30.7, and the rest of the array is 0.0:

W : Vector500 := Vector500'(10 => 1.3, 15 => -30.7,
others => 0.0);

Sometimes we must qualify an aggregate when others is used with named notation;
at other times it's optional. The rules (
Ada 95 RM section 4.3.3, paragraphs 10-15) are complicated. It's easiest always to qualify an aggregate when
others follows named notation, as shown above.

In array aggregates, multiple choices can be denoted with the vertical bar (|),
shift-backslash on PC keyboards. In this array, the elements with odd
subscripts are True, while the elements with even subscripts are False:

Here we assigned to D1 with an executable statement for variety; we could also
have initialized D1 in the declarative region with the same aggregate. Some
people read the vertical bar as "and," others as "or." One can say, "Elements
1, and 3, and 5, and 7, and 9 are True," or one can say, "If the subscript is
1, or 3, or 5, or 7, or 9, the array element is True."

No. Indeed Vowels(Letter) is Vowels('E'), which is True, but the program takes
the Boolean'Pos of Vowels(Letter). Recall that the attribute 'Pos converts
from a discrete type (in this case, Boolean) to an integer.

No. While Letter is 'E', and Letter appears inside the Put statement, the
parameter of Put is the Boolean'Pos of one element of array Vowels
(specifically, the element whose subscript is 'E'). Recall that the 'Pos
attribute always returns an integer.

In an array declaration or an array type declaration, we may totally omit the
range of the subscript (not even supplying a box), if the type or subtype of
the subscript has a reasonable number of possible values. (We did that in the
declaration of type Set_Of_Unaccented_Letters in the last question.) For
example, in

we have an array of seven Floats, because there are seven possible values of
type Rainbow_Color. Similarly,

V :array(Character)ofBoolean;

creates an array of 256 Booleans (128 in Ada 83). However,
J : array(Integer) of Float; is an attempt to declare a very large array
indeed! In a case like this, we can use a subtype in the subscript
declaration. The following creates an array of 31 Floats:

Here Mv'First and My_Vector'First are both 30. Mv'Last and My_Vector'Last are
both 33. Note that 'First and 'Last refer to the subscripts, not to the values
of the array elements. Thus Mv'First is not 1000. To obtain the value of the
first element, we would use Mv'First as a subscript. Mv(Mv'First) is 1000.

The attribute 'Range is an abbreviation for 'First .. 'Last. It can be used
with array types and array names, and (in Ada 95 only), with scalar types.
Thus Mv'Range and My_Vector'Range both mean 30 .. 33. In Ada 95, we can write
Integer'Range as an abbreviation for Integer'First .. Integer'Last. The
attribute 'Length is also available: Mv'Length and My_Vector'Length are both 4.