home *** CD-ROM | disk | FTP | other *** search
-
-
-
- Chapter 20
- ADVANCED RECORD TOPICS
-
-
- A RECORD WITH A DISCRIMINANT
- _________________________________________________________________
-
- Examine the file named DISCRIM1.ADA for our ================
- first example of a record with a discriminant. DISCRIM1.ADA
- It will take a little time and study before we ================
- get to the discriminant and what it does, but we
- will take it a step at a time.
-
- We begin by defining an unconstrained two dimensional array type
- in line 10 of the declaration part, and an unconstrained one
- dimensional array type in line 13. Next we define a record type,
- beginning in line 15, with a discriminant, the discriminant being
- a variable named List_Size which is of type POSITIVE. The record
- is composed of four fields, each of which is defined in part by the
- discriminant. The variable named Matrix is a square array whose
- size is given by the value of the discriminant, while Elements is
- initialized to the square of the discriminant. Likewise, the other
- two fields are defined as a function of the discriminant. Keep in
- mind that the discriminant still does not have a value, it is only
- used as a part of the pattern of the record.
-
- For later use, we define a derived type in line 23, and a subtype
- in line 25. The subtype is defined as being of type STUFF but with
- the discriminant being fixed at 5. We will have more to say about
- these two types later.
-
-
-
- WE NEED TO DEFINE SOME DATA NOW
- _________________________________________________________________
-
- In line 27, we declare a variable named Data_Store to be of type
- STUFF with the discriminant set equal to 5. Therefore, the Matrix
- variable which is a part of the record named Data_Store will have
- two subscripts, each of which covers a range of 1 through 5. The
- variable named Elements will be initialized to the square of 5, and
- the other fields will likewise be defined. The variable Big_Store
- will have larger arrays, and the value of its subfield, named
- Elements, will be initialized to a value of the square of 12.
- Since these two variables have different numbers of elements, they
- are not assignment compatible, nor can they be compared for
- equality or inequality.
-
- The variable Extra_Store is declared as being of type ANOTHER_STUFF
- with a discriminant of 5, but since the types are different, this
- variable is not assignment compatible with the first variable named
- Data_Store. More_Store is declared as being of type STUFF with a
- discriminant of 5, so it is assignment compatible with Data_Store.
-
- Page 20-1
-
- Chapter 20 - Advanced Record Topics
-
- Five_Store, because it is a subtype of STUFF, and its discriminant
- is 5, as defined in the subtype declaration, is assignment
- compatible with Data_Store. Finally, it should be clear that the
- last example, Name_Store, is assignment compatible with Data_Store,
- since its only difference is that it uses the named method of
- discriminant selection. This is a hint to you that additional
- discriminants can be used, and there is actually no limit to the
- number that can be a part of a discriminated record type. We will
- have an example program soon that has three discriminants.
-
-
-
- WHO IS ASSIGNMENT COMPATIBLE WITH WHO?
- _________________________________________________________________
-
- As mentioned before, the variables named Data_Store, More_Store,
- Five_Store, and Name_Store, are all of the same type and can be
- freely assigned to each other. They can also be compared for
- equality or inequality with each other. The other variables are
- of different types and cannot be assigned as a complete record to
- each other, or compared for equality or inequality.
-
- The discriminant, once declared, is considered to be a constant,
- and cannot be modified. The discriminant of the variable
- Data_Store is accessed in the program as Data_Store.List_Size for
- purposes of reading it. The executable part of the program should
- be clear. One of the declared Matrix variables is assigned values
- using the RANGE attribute for the loop limits. The entire record
- is then assigned to some additional record variables, and a single
- data point is displayed as an example.
-
- When you understand the program, compile and execute it to prove
- to yourself that it works as shown. Notice that, as always, the
- elements of the record cannot be anonymous types but must be named.
-
-
-
- HOW DO WE USE THE NEW RECORDS?
- _________________________________________________________________
-
- Examine the example program named DISCRIM2.ADA ================
- for a few examples of how to use the DISCRIM2.ADA
- discriminated record. The type declarations are ================
- identical to the last program, but only two
- records are declared this time, Data_Store and
- Big_Store, which are of different types because they have different
- discriminants.
-
- The declaration part of the program has a function declaration and
- a procedure declaration added to it in this program. If you look
- closely, you will see that the type used for the formal variable
- in both subprograms is of the record type STUFF, but there is no
- discriminant defined for either. These are unconstrained records
- and add flexibility to the use of subprograms. The loops within
-
- Page 20-2
-
- Chapter 20 - Advanced Record Topics
-
- the subprograms use limits that are dependent upon the limits of
- the actual type as defined in the calling program, and the
- subprograms can therefore be used for any record variable of type
- STUFF regardless of the value of the discriminant.
-
-
-
- USE OF THE UNCONSTRAINED SUBPROGRAMS
- _________________________________________________________________
-
- The nested loop in lines 48 through 53, assigns the elements
- contained in the array variable Data_Store.Matrix to a
- multiplication table for later use. In line 55, we call the
- procedure Set_To_Ones with the record Big_Store to set all of its
- Matrix values to 1. Finally, we display the sums of all of the
- elements by calling the function Add_Elements once for each record.
- Even though the records are actually of different types, the
- function works correctly with both, because of the flexibility
- built into the function itself. Note that even though the record
- is unconstrained in each subprogram, it is constrained when the
- subprogram is called since the discriminant is constrained to the
- value of the actual parameter in the call.
-
- Be sure to compile and execute this program and study the output
- until you are sure you understand the results.
-
-
-
- A VARIABLE DISCRIMINANT
- _________________________________________________________________
-
- Examine the program named DISCRIM3.ADA for an ================
- example of a discriminant that can be changed DISCRIM3.ADA
- dynamically. This program is nearly identical ================
- to the last example program, but there are two
- very small changes. The discriminant is
- initialized to a value of 2 in line 15, which will be used for the
- discriminant if none is given in the variable declaration. This is
- illustrated in line 25, where the variable Var_Store is declared
- to be of type STUFF, and is defaulted to the initialization value
- of 2 for its discriminant. There is one other property that it has
- acquired, and that is the ability to have its discriminant changed
- to any legal value during execution of the program.
-
- The two variables named Data_Store and Big_Store have their
- discriminants fixed at 5 and 12 respectively and cannot be changed
- during program execution.
-
-
- HOW DO WE CHANGE THE DISCRIMINANT?
- _________________________________________________________________
-
- The discriminant can only be changed by changing the entire record
- in a single statement as is illustrated in line 56 where the entire
-
- Page 20-3
-
- Chapter 20 - Advanced Record Topics
-
- record named Data_Store, with a discriminant of 5, is assigned to
- the variable Var_Store. The variable Var_Store can then be used
- anywhere it is legal to use a record of discriminant 5 as shown in
- lines 57 through 63. Note that prior to the assignment in line 56
- the variable Var_Store can be used as a record with its
- discriminant set to 2 as the default.
-
- In line 67, the variable Var_Store is assigned the entire record
- of Big_Store which effectively changes it into a record variable
- with a discriminant of 12. The fact that it is changed is
- evidenced by the output which you can see after you compile and
- execute this program. Note that all of the values contained in
- Big_Store are copied into Var_Store. Be sure to compile and
- execute this program.
-
-
-
- A MULTIPLE DISCRIMINANT
- _________________________________________________________________
-
- Examining the example program named DISCRIM4.ADA ================
- gives you an example of how to use a multiple DISCRIM4.ADA
- discriminant in a record type. The first ================
- difference is in lines 15 through 17 where three
- discriminants are defined for the record type,
- and the next big difference is in lines 25 through 31 where 5
- variables are declared with this type illustrating the various
- kinds of discriminant initialization described in this chapter.
-
- Since we have studied all of these in the last few example
- programs, we will not elaborate on them, except to mention that the
- variable named Variable can be assigned the value of any of the
- other variables. It will then have the entire set of discriminants
- assigned to it that the assignment variable possesses and it will
- be assigned all of the current values stored in the source record.
- This is exactly the same as what was illustrated in the last
- program.
-
- Be sure to compile and run this program after you understand the
- concepts it is meant to convey to you.
-
-
-
- A VARIANT RECORD
- _________________________________________________________________
-
- Examine the file named VARIANT1.ADA for our ================
- first example of a variant record. A variant VARIANT1.ADA
- record must have a discriminant, by definition, ================
- since the discriminant will define which of the
- various variants each record variable will be
- composed of. If you are a Pascal programmer you will find the
- variant record to be much more confining than in Pascal where you
- can change the variant at will. If you remember that Ada is a very
-
- Page 20-4
-
- Chapter 20 - Advanced Record Topics
-
- strongly typed language, and will accept no deviation from its
- defined standard in order to detect errors inadvertently introduced
- by the programmer, you will appreciate the terse definition and
- restrictions.
-
- The discriminant for our example record is declared in line 10 as
- an enumerated type with four allowable values. A variable named
- Engine is declared, which is of type POWER, which will be used as
- the discriminant and two variables are declared as the first part
- of the record. The variant part of the record begins in line 16
- with the reserved word case followed by the name of the
- discriminant variable, which is Engine in this example. The four
- variants are declared in much the same way as a normal case
- statement with variable declarations in place of the executable
- statements. There must be a clause listed for each possible value
- of the discriminant, and any number of variables may be defined for
- each, including none. If no variables are declared for a case, the
- reserved word null is used to indicate to the compiler that you
- really mean to include no variables there.
-
- If there is a variant to the record, it must be the last part of
- the record with all common variables declared first. One or more
- of the variant parts of the record can have a variant part itself,
- provided it is the last part of the variant part. There is no
- defined limit to the nesting.
-
-
-
- HOW DO WE USE THE VARIANT RECORD?
- _________________________________________________________________
-
- In line 25, we declare the variable Ford to be a record of type
- VEHICLE, and constrain it to be the GAS variant of the record.
- Because the Ford variable is constrained to the GAS variant, it can
- only use the variable declared as part of the GAS variant, and of
- course the two common variables. It would be illegal to assign
- data to the fields of the Ford variable which are declared in the
- other variants of the record type. Moreover, since the variable
- Ford has been assigned the discriminant value of GAS, it can never
- be changed, but is a constant. Likewise, the variable named Truck
- will always be a record of type VEHICLE with the variant DIESEL
- because that is what it is declared with. The same is true of the
- other two variables declared in lines 27 and 28. We will see in
- the next program, that it is possible to declare a variable in such
- a way that it can be modified dynamically to any of the variants
- as the program is executing.
-
-
-
- HOW DO WE ASSIGN VALUES TO THE VARIABLES?
- _________________________________________________________________
-
- Lines 32 through 34 should be familiar to you since this is the
- method used to assign values to a record with no variant, which we
-
- Page 20-5
-
- Chapter 20 - Advanced Record Topics
-
- studied earlier. Line 36 illustrates value assignment by using a
- positional aggregate notation, and line 39 illustrates assignment
- of values using the named aggregate notation. In both of these
- cases, all four fields must be named even if some are not changed.
- Even the invariant discriminant must be included in the aggregate,
- which seems to be somewhat of a nuisance, since it is a constant.
- The reasons for these last two rules are probably well founded and
- have to do with ease of writing a compiler, which is certainly no
- small job.
-
- The statements in lines 42 through 45 assign values to each of the
- subfields of the record variable named Stanley, and the mixed
- aggregate assignment is illustrated in line 47, where all five
- variables are mentioned even though the discriminant is a constant.
- Finally, the Schwinn and Truck variables are assigned values in
- lines 50 through 56. Compile and execute this program to assure
- yourself that your compiler will indeed compile it correctly.
-
-
-
- A VARIABLE VARIANT RECORD
- _________________________________________________________________
-
- Examine the program named VARIANT2.ADA for an ================
- example of a variant record in which we can VARIANT2.ADA
- change the variant dynamically during program ================
- execution. A major difference here is that the
- discriminant is defaulted to the value listed in
- line 12, namely the value of NONE. If no variant is declared, it
- is defaulted to NONE in the declarations as is done in line 25,
- where three variable records are declared using the default value
- of the discriminant. The variable Stanley is once again declared
- to be of the variant STEAM, and this will remain constant
- throughout the execution of the program, because any variable
- declared with a discriminant value cannot have the value of its
- discriminant changed dynamically but is a constant, although the
- individual elements of the record can be changed.
-
-
-
- NOW TO USE SOME OF THE NEW VARIABLES
- _________________________________________________________________
-
- In line 30, the variable Ford is assigned data such that it is of
- the GAS variant, using the positional aggregate notation, and is
- redefined in the next statement to be of the DIESEL variant, by
- using the mixed aggregate notation. This is done to illustrate to
- you that it is possible to change the variant of a variable if it
- was declared with the default variant. In line 33, the variable
- Truck is assigned the DIESEL variant with the positional aggregate
- notation, and two of the fields are changed in the next two
- statements.
-
-
-
- Page 20-6
-
- Chapter 20 - Advanced Record Topics
-
- Any of the fields can be changed individually with the exception
- of the discriminant variable, which can only be changed by use of
- an aggregate in which all values are listed. Remember that this
- is the aggravating part of this construct, that all of the fields
- must be mentioned in every record aggregate. Even though you can
- change individual values of the record, you are limited to using
- those variables that are part of the current variant. Pascal
- allows you to use variable names of other variants but Ada will not
- permit this. You are permitted to use the positional, named, or
- mixed aggregate notation, however. Be sure to compile and execute
- this program after you understand the concepts.
-
-
-
- OPERATOR OVERLOADING
- _________________________________________________________________
-
- The example program named INFIX.ADA could be ===============
- placed in several different places in this INFIX.ADA
- tutorial, because it doesn't really fit anywhere ===============
- too well. Since one of the most advantageous
- places to use operator overloading is with
- record type variables, this seemed like a good place for it. The
- program itself is very simple, but the concept is potentially very
- powerful.
-
- We first define a record composed of three simple variables all
- being of type INTEGER, and use this definition to declare three
- variables of this type. The next declaration is of a function
- named "+", which we can define to do anything we wish it to do.
- In this case we input two variables of the record type THREE_INTS
- and return one record of the same type. Within the function, we
- add all three fields of one variable to the corresponding fields
- of the other variable, and return the record consisting of the sum
- of the two input records. To make it even more convenient, Ada
- allows you to use the overloaded operator in an infix notation as
- illustrated in line number 33 of the program where two records are
- added together and assigned to the record variable named Sum. This
- line is actually a call to the function we defined earlier and
- named "+".
-
- It could be a bit confusing if you consider the addition in line
- 27 where the usual addition operator is used. Ada will decide
- which + operator to use based on the type of the constants or
- variables to be added together. If you were to try to use this
- operator on a record of some other type, such as the VEHICLE record
- from the last program, the system would generate a type error
- during compilation. As mentioned previously, it is only possible
- to overload existing operators. You cannot define a new operator,
- such as &=, and use it for some operation.
-
- Recall the chapter named Advanced Array Topics where we overloaded
- the "+" operator in the example program named ARRAYOP2.ADA. Both
- overloadings of this operator could be included in a single program
-
- Page 20-7
-
- Chapter 20 - Advanced Record Topics
-
- and the system would be able to find the correct overloading for
- each use by checking the types used. Be sure to compile and
- execute this program even though it has no output.
-
-
-
- PROGRAMMING EXERCISES
- _________________________________________________________________
-
- 1. Add some output statements to VARIANT1.ADA to display some of
- the results.
-
- 2. Try to change the variant of Stanley in the same way we
- changed the variant of Ford in the example program named
- VARIANT2.ADA to see what kind of error messages you get.
-
- 3. Add another overloading function to INFIX.ADA which uses the
- "+" operator to add all six elements of two records together
- and return a single INTEGER type variable. The system can
- tell which overloading you wish to use by the return type
- associated with the function call.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 20-8