ADVANCED ARRAY TOPICS
Example program ------> SUMMER.ADA
Examine the file named SUMMER.ADA for an example of an unconstrained array type illustrated in line 10. The box (<>), as it is called, refers to something that must be filled in later, and is a construct that will be used many other places in Ada. Note that the index type in line 10 is POSITIVE, a fact that will have a bearing on its use later.
USE OF THE UNCONSTRAINED ARRAY TYPE
In line 12, we declare an array constant of type MY_ARRAY and we assign values to the constants by use of the positional aggregate. Since we do not give the range of the indices of the array, the system will assign them, and in this case will use a range of 1 through 4, because of the use of the type POSITIVE for the index type. If we would have used type INTEGER for the index, the selected range would have been -32768 through -32765, which is the lower end of the INTEGER range, unless your implementation used a different lower limit for INTEGER. Careful selection of the array index type is important. In line 13, we declare another constant array, but this time we use a named aggregate and the system does not get the opportunity to pick the range, we pick it explicitly ourselves. The indices do not have to be named in consecutive order as is done here, but all values must be given.
We declare an uninitialized variable array in line 16, which covers the range of 1 through 12, and an initialized variable array in line 17, which uses the positional aggregate method of initialization.
A VERY FLEXIBLE FUNCTION
The function in lines 20 through 30 appears to use an unconstrained array for its formal parameter variable, and it does, but with each use of the function, the formal parameter array is constrained to the limits of the actual variable. When the function is called in line 36 of the program with My_List as the actual array variable, the range of My_List, 1 through 12, is used for the range of the formal parameter in the function. This makes it possible to use the array attributes within the function, in the manner shown, such that they are dependent on which array is used for the actual parameter. When Stuff is used for the actual parameter, the formal parameter will have a range of 4 through 8 within the function. The function can therefore be written in such a way that it has flexibility built into it, even though strong type checking continues to be done, since the function cannot be used with a different unconstrained type if we had one in this example program. Note that all array attributes are available here as they are with any array.
A FEW NOTES ABOUT THIS TYPE
All elements of every variable of type MY_ARRAY will be of type INTEGER, and all indices will be of subtype POSITIVE including the range limits. The variables named My_List and Stuff are of the same type with different limits, so the slice can be used with them. After you study this program, compile and execute it so you can observe the output.
AN ARRAY WITH AN ENUMERATED INDEX
Example program ------> ENUMARY.ADA
Examine the program named ENUMARY.ADA for an example of an array with an enumerated variable for an index. Since the index of an array may be any discrete type, and an enumerated type is discrete, it can be used for an array index according to the Ada standard.
We define an enumerated type named DAY, that includes the days of the week as elements, then declare an array using the type DAY for the index. It should be apparent to you that this is an anonymous array type, the use of which is discouraged in a significant program, but should cause no type conversion problems in a simple program such as this one. Finally, we declare two other simple variables for later use and begin the executable part of the program.
We use a loop to assign 8.0 hours to each day from MON through FRI, then assign 4.0 hours to SAT, and 0.0 hours to SUN. Finally we sum up the hours for the week and display them on the monitor. It is a very simple program, but it illustrates a very useful construct in Ada. For that reason, you should spend enough time studying it until you thoroughly understand it. Be sure to compile and execute ENUMARY.ADA.
ARRAY OPERATORS
Example program ------> ARRAYOPS.ADA
Some of the operators discussed earlier in this tutorial are available for use with arrays. They operate on each element of the array as if the operation were done in a loop. The example program ARRAYOPS.ADA will illustrate the use of a few of these operations.
Lines 22 through 27 illustrate the logical operators being used with entire arrays. The arrays are compared element by element, and as soon as a difference is found in two corresponding elements, the comparison result of these two elements is returned as the overall comparison result. If all corresponding elements are equal, the result of the comparison is equal.
Note that it is legal and sometimes very useful to use an array of records. Arrays of records can be compared for equality or inequality, but not for the other four operators ( >, >=, <, <= ) because they are illegal for use with individual record elements. Some thought on your part would have led to this conclusion without us explicitly stating it. Many such combinations of operations are possible with Ada. It will be up to you to try a few yourself, as you need them, because there are too many permutations for us to delineate all of them.
ARITHMETIC ARRAY OPERATORS
The operators illustrated in comments in lines 29 through 34 are not available as a part of Ada, but they can be made available to your programs by use of an extension to the language. The method will be illustrated in the next example program.
BOOLEAN ARRAY OPERATORS
Two BOOLEAN arrays are assigned some values using positional aggregates in lines 36 and 37, then used in lines 39 through 46 as complete arrays. The logical operators are used in much the same way that the comparison operators were used previously in this file. Note that these operators result in another array, each element being the result of the logical operation of the corresponding elements in the compared arrays. The comparison operators are available with boolean arrays in a manner similar to that with other scalar arrays, only a single BOOLEAN type result value is returned. Compile and run this program after you understand the new material presented.
HOW TO WRITE THE ARITHMETIC ARRAY OPERATORS
Example program ------> ARRAYOP2.ADA
The example program named ARRAYOP2.ADA illustrates how to write the arithmetic array operators. This is actually an overloading of the usual arithmetic operators. Overloading these operators is nothing new, you have been doing it all through this tutorial, because the plus sign, for example, has been available for adding integer types, as well as fixed and floating point types. There is no reason the plus sign could not be used to add arrays, element by element, and that is exactly what we will illustrate here.
The "+" function is listed in lines 14 through 21 and is a very simple function, with no difficult code. The name of the function is the unusual thing about this function, its name being "+". This is the Ada method of overloading operators, and after the function is defined it is called by using an infix notation, as illustrated in line 37 of the program where all 6 elements of Group1 are added to the corresponding elements of Group2, and the 6 results being assigned to the 6 elements of Crowd. The results of the addition are displayed in lines 38 through 43 to show that all elements were summed.
In a similar manner, the function named "mod" is used to provide an infix notation for the modulo operator, and is called in line 48. The other four arithmetic operators are not defined here since they are so similar to the two which are illustrated. The overloading of the mod operator in this way should indicate to you why it is important to think of mod as an operator rather than a subprogram call.
OVERLOADING RULES
There are two rules which must be considered when overloading operators, the first being that you are permitted as many overloadings for a given operator as you desire, provided that the parameters of the inputs and result have unique types for each of the overloadings. This is because the system uses the types of the parameters and the type of the result to determine which overloading you wish to use each time you use the operator. This implies, correctly, that you cannot redefine the use of an existing operator for a given type.
The second rule is simple. You can overload existing Ada operators, but you cannot define an infix operator that is not predefined in Ada. Be sure to compile and execute this program.
UNARY OPERATOR OVERLOADING
Example program ------> UNARYOP.ADA
Examine the program named UNARYOP.ADA for an example of overloading the unary operators "+" and "-". The function in lines 32 through 35 overloads the "+" operator for the array defined and is of little interest since nothing is really accomplished here. The function in lines 37 through 44 overloads the "-" operator and negates each element of the array. It may seem silly to even bother with overloading the "+" operator, but it is illustrated here and can be used to advantage when we come to a study of generic packages. It may be necessary to allow use of such a seemingly silly construct in order to write a general purpose generic package.
Be sure to compile and run this program and see that the illustrated overloadings work as we have stated.
OPERATOR HIDING
In all of the overloadings we have examined, we were careful to use overloadings that introduced new type combinations so there was never an instance of hiding another subprogram. If the type combinations are already overloaded in a global manner when a further overloading is declared at a lower level of nesting, the subprogram called by the global combination will be hidden and the nested subprogram will be called each time. Even though care must be exercised when overloading operators or identifiers, do not fear use of this powerful technique made available to you by the designers of Ada.
PROGRAMMING EXERCISES