The purpose of unconstrained array types is to allow subprograms that operate on arrays to be written without prior knowledge of the bounds of the arrays. Let us start with a type definition:
TYPE ListType IS ARRAY (Integer RANGE <>) OF Float;The construct
Integer RANGE <>
means that the subscript range,
or bounds, of any variable of type ListType
must form an integer
subrange; the symbol "<>
" is read "box" and means "we'll
fill in the missing range when we declare ListType
variables."
The type ListType
is said to be unconstrained. When
variables are declared, the compiler must know how much storage to allocate,
and so each variable declaration must carry a range constraint, for
example:
L1 : ListType(1..50); -- 50 elements L2 : ListType(-10..10); -- 21 elements L3 : ListType(0..20); -- 21 elements
The operations of assignment and equality testing are defined for unconstrained
array types, but for either operation to proceed without raising
Constraint_Error
, both operands must be variables of the same
unconstrained array type and both operands must have the same number of
elements. So
L1 := L2;will raise
Constraint_Error
, but the following operations will all
succeed:
L2 := L3; L1 (20..40) := L2; L2 (1..5) := L1 (6..10);These slicing operations were introduced in Chapter 9 in the discussion of Ada strings. Ada's string type is actually defined in
Standard
as
follows:
TYPE String IS ARRAY (Positive RANGE <>) OF Character;making strings just a special case of unconstrained arrays. The slicing operations work for all one-dimensional arrays just as they do for strings.
ListType
above and the
variable L2
,
L2'First
returns the low bound of L2
, or -10 in this
case.
L2'Last
returns the high bound of L2
, or 10.
L2'Length
returns the number of elements in L2
, or
21.
L2'Range
returns the range -10..10.
The last attribute is useful in controlling loops, for instance,
FOR WhichElement IN L2'Range LOOP My_Flt_IO.Put(Item=>L2(WhichElement), Fore=>1, Aft=>2, Exp=>0); Text_IO.New_Line; END LOOP;The construct
L2'Range
is a short way of writing
L2'First..L2'Last
, so the same fragment could be written
FOR WhichElement IN L2'First..L2'Last LOOP My_Flt_IO.Put(Item=>L2(WhichElement), Fore=>1, Aft=>2, Exp=>0); Text_IO.New_Line; END LOOP;
To show the utility of unconstrained arrays, consider a function to find the
maximum value stored in an array of floating-point numbers. For this function
to be generally useful and reusable, it needs to be able to work for all kinds
of floating-point arrays, no matter what their bounds. Using the type
ListType
,
Program
11.1 shows such a function contained in a test program. The program also
contains a procedure DisplayList
, which displays the contents of a
ListType
variable, whatever its bounds. The main program declares
two lists of differing bounds, then displays the lists and tests the function
MaxValue
. From the output of the program, you can see that the
maximum is found correctly even though the two lists have different sizes.
Program 11.1
WITH Ada.Text_IO; WITH Ada.Float_Text_IO; PROCEDURE Test_Max_Value IS ------------------------------------------------------------------------ --| Illustrates use of unconstrained array types --| Author: Michael B. Feldman, The George Washington University --| Last Modified: September 1995 ------------------------------------------------------------------------ TYPE ListType IS ARRAY(Integer RANGE <>) of Float; L1 : ListType(1..5); -- 5 elements L2 : ListType(-4..3); -- 8 elements -- local procedure to display the contents of a list PROCEDURE DisplayList(L: ListType) IS -- Pre: L is defined -- Post: display all values in the list BEGIN -- DisplayList FOR Count IN L'Range LOOP Ada.Float_Text_IO.Put(Item=>L(Count), Fore=>3, Aft=>1, Exp=>0); END LOOP; Ada.Text_IO.New_Line; END DisplayList; FUNCTION MaxValue(L: ListType) RETURN Float IS -- Pre: L is defined -- Post: returns the largest value stored in L CurrentMax : Float; BEGIN -- MaxValue CurrentMax := Float'First; -- minimum value of Float FOR WhichElement IN L'Range LOOP IF L(WhichElement) > CurrentMax THEN CurrentMax := L(WhichElement); END IF; END LOOP; -- assert: CurrentMax contains the largest value in L RETURN CurrentMax; END MaxValue; BEGIN -- Test_Max_Value L1 := (0.0, -5.7, 2.3, 5.9, 1.6); L2 := (3.1, -2.4, 0.0, -5.7, 8.0, 2.3, 5.9, 1.6); Ada.Text_IO.Put(Item=> "Testing MaxValue for float lists"); Ada.Text_IO.New_Line; Ada.Text_IO.New_Line; Ada.Text_IO.Put(Item=> "Here is the list L1"); Ada.Text_IO.New_Line; DisplayList(L => L1); Ada.Text_IO.Put(Item=> "The maximum value in this list is "); Ada.Float_Text_IO.Put(Item => MaxValue(L=>L1), Fore=>1, Aft=>2, Exp=>0); Ada.Text_IO.New_Line; Ada.Text_IO.New_Line; Ada.Text_IO.Put(Item=> "Here is the list L2"); Ada.Text_IO.New_Line; DisplayList(L => L2); Ada.Text_IO.Put(Item=> "The maximum value in this list is "); Ada.Float_Text_IO.Put(Item => MaxValue(L=>L2), Fore=>1, Aft=>2, Exp=>0); Ada.Text_IO.New_Line; END Test_Max_Value;Sample Run
Testing MaxValue for float lists Here is the list L1 0.0 -5.7 2.3 5.9 1.6 The maximum value in this list is 5.90 Here is the list L2 3.1 -2.4 0.0 -5.7 8.0 2.3 5.9 1.6 The maximum value in this list is 8.00
SYNTAX DISPLAY
Unconstrained Array Type
TYPE ArrayType IS ARRAY (IndexType RANGE <>) OF ValueType ;
SUBTYPE DaysInYear IS Positive RANGE 1..366; SUBTYPE Temperature IS Float RANGE -100.0 .. 200.0; TYPE TemperatureReadings IS ARRAY (DaysInYear RANGE <>) OF Temperature;
Temps: TemperatureReadings;
Temps: TemperatureReadings (1..31);
In Section 9.1 we studied array slicing in the
context of strings. Slicing
is actually more general: It is available for all one-dimensional
unconstrained arrays in Ada. For example, given the function
MaxValue
from Program 11.1 and a Float
variable
Y
, it is permissible to call MaxValue
with a slice as
its parameter, as in
Y := MaxValue(L => L2(0..2));which would search only the given slice of the array for a maximum value. As an exercise, you can modify Program 11.1 to test this concept.
MaxValue
with parameters L1(2..4)
,
L2(0..2)
, and L2(-4..-1)
and ascertain that the
program correctly finds the given maximum values.
Copyright © 1996 by Addison-Wesley Publishing Company, Inc.