home *** CD-ROM | disk | FTP | other *** search
-
-
-
- Chapter 8
- SUBPROGRAMS
-
-
- LET'S LOOK AT A PROCEDURE
- _________________________________________________________________
-
- Ada was designed to be very modular, and we come ===============
- to the point where we will study the first and PROCED1.ADA
- simplest form of modularization, the procedure. ===============
- If you examine the program named PROCED1.ADA,
- you will have your first example of a procedure.
- Some languages call this kind of subprogram a subroutine, others
- a function, but Ada calls it a procedure.
-
-
- THE PROCEDURE IS LIKE THE MAIN PROGRAM
- _________________________________________________________________
-
- Beginning with the executable part of the main program, we have two
- executable statements in lines 14 and 15, each calling a procedure
- to write a line, if the name has any meaning. As always, the two
- statements are executed in succession, and each statement is a
- procedure call to which we would like to transfer control. The
- procedure itself is defined in lines 7 through 11, and a close
- inspection will reveal that the structure of the procedure is very
- similar to the structure for the main program. It is in fact,
- identical to the main program, and just as we begin executing the
- main program by mentioning its name, we begin executing the
- procedure by mentioning its name. The procedure has a declarative
- part, which is empty in this case, and an executable part which
- says to display a line of text and return the cursor to the
- beginning of the next line.
-
- When execution reaches the end statement of the procedure, the
- procedure is complete and control returns to the next successive
- statement in the calling program.
-
- Everything we have said about the main program, which is actually
- a procedure, is true for the procedure. Thus we can define new
- types, declare variables and constants, and even define additional
- procedures in the declarative part of this procedure. Likewise,
- we can call other procedures, and do assignments and compares in
- the executable part of the procedure.
-
-
-
- ORDER OF DECLARATIONS
- _________________________________________________________________
-
- The procedure must come after all type, constant, and variable
- declarations. Ada forces you to arrange your program such that all
- of the smaller declarations must come first, followed by the larger
-
- Page 8-1
-
- Chapter 8 - Subprograms
-
- ones. This is so that the small declarations don't get lost among
- the bigger ones.
-
- The embedded procedure has all of the flexibility and requirements
- as those defined for the main procedure. We will give further
- examples of each of these points in the next few example programs.
- At this time, compile and run this program, and make sure you
- understand its operation completely.
-
-
- THREE PROCEDURES
- _________________________________________________________________
-
- Examine the program named PROCED2.ADA, and you ===============
- will see three procedures in the declarative PROCED2.ADA
- part of this program. Jumping ahead to the main ===============
- program, beginning in line 33, you will see that
- the program will write a header, write and
- increment something 7 times, then write an ending statement.
- Notice how the use of descriptive procedure names resulted in our
- understanding of what the program will do without looking at the
- procedures themselves. The names are long, and a bit tedious to
- type in, but since Ada was designed to be a language that would be
- written once and read many times, the extra time will pay off when
- the source code is studied by several persons in the future.
-
-
- WHAT IS A GLOBAL VARIABLE?
- _________________________________________________________________
-
- The variable named Counter, defined in line 10, is a global
- variable because it is defined prior to any procedure. It is
- therefore available for use by any of these procedures and it is,
- in fact, used by two of them. In line 14, the variable Counter is
- assigned the value of 1 when the procedure named Write_A_Header is
- called. Each time Write_And_Increment is called, the current value
- of Counter is written to the display, along with a message, and the
- value is incremented. Note carefully that the procedures are not
- executed in the order they are because of their relative order, but
- because the main program calls them in that order. The program
- would work exactly the same way if you moved the first procedure,
- in its entirety of course, after the procedure
- Write_An_Ending_Statement. The order of execution is controlled
- by the order of calls, not the physical order of the procedures.
-
-
- WHY DO PROCEDURES GO IN THE DECLARATIVE PART?
- _________________________________________________________________
-
- The declarative part of the program is where we define entities for
- use within the executable part. The procedures are actually
- definitions of how to do something, so they are right where they
- belong, but they must come after the smaller declarations. To
- reiterate a rule stated earlier, the variable must be declared
-
- Page 8-2
-
- Chapter 8 - Subprograms
-
- prior to the procedure declarations so that it does not get lost
- among the procedures. Compile and run this program and be sure you
- understand the output.
-
-
- A PROCEDURE WITH PARAMETERS
- _________________________________________________________________
-
- Examine the file named PROCED3.ADA and you will ===============
- find a procedure that requires some data to be PROCED3.ADA
- supplied to it each time it is called. Three ===============
- variables are defined as type INTEGER and used
- in the procedure call in line 28. We will
- ignore the strange looking constructs in lines 12 through 15 for
- a couple of paragraphs. The procedure header, beginning in line
- 18, states that it is expecting three inputs, and each must be of
- type INTEGER, so we are compatible so far. When the procedure is
- called, the value of the first variable, which is named Dogs in
- this case, is taken to the procedure, where the procedure prefers
- to refer to it by the name Variety1. In like manner, the value of
- Cats is given to the procedure, and is called Variety2. The
- variable named Animals is referred to by the name Total in the
- procedure. The procedure is now ready to do some meaningful work
- with these variables, but is somewhat limited in what it can do to
- them because of the mode field of the procedure header.
-
-
- THE MODE OF A PARAMETER
- _________________________________________________________________
-
- The formal parameter, as it is called in the procedure header,
- named Variety1, is of mode in which means that it is an input
- parameter, and therefore cannot be changed within the procedure.
- Variety1, along with Variety2 for the same reason, is a constant
- within the procedure, and any attempt to assign a value to it will
- result in a compile error. The formal parameter named Total,
- however, is of mode out and can therefore have a new value assigned
- to it within the procedure. It is illegal to attempt to read this
- variable within the procedure, because it is of output mode only.
- If it were defined as being of mode in out, it could be both read
- from and written to. If no mode is given, the system will use mode
- in as a default.
-
-
- PARAMETER MODE SELECTION
- _________________________________________________________________
-
- All variables could be defined as mode in out and there would be
- no problems, since there would be maximum flexibility, or so it
- would seem. There is another rule that must be considered, and
- that rule says that every parameter that is of mode out or in out
- must be called with a variable as the actual parameter in the
- calling program. A variable of mode in can use a constant or a
- variable for the actual parameter in the calling program. We have
-
- Page 8-3
-
- Chapter 8 - Subprograms
-
- been using the New_Line procedure with a constant in it, such as
- New_Line(2), and if it had been defined with the formal parameter
- of mode in out, we would have had to define a variable, assign the
- value 2 to it, and use the variable in the call. This would have
- made the procedure a bit more difficult to use, and in fact,
- somewhat awkward. For this reason, the formal parameter in
- New_Line was defined using mode in. You should choose the mode of
- the formal parameters very carefully.
-
- The three formal parameters are available for use in the procedure,
- once they are defined as illustrated, just as if they had been
- defined in the declarative portion of the procedure. They are not
- available to any other procedure or the main program, because they
- are defined locally for the procedure. When used however, their
- use must be consistent with the defined mode for each.
-
-
- SOME GLOBAL VARIABLES
- _________________________________________________________________
-
- The three variables declared in line 10 can be referred to in the
- procedure as well as in the main program. Because it is possible
- to refer to them in the procedure, they can be changed directly
- within the procedure. The variable Animals can also be modified
- when control returns to the main program because it is declared of
- out mode in the procedure header. This possibility can lead to
- some rather unusual results. You should spend some time thinking
- about what this really means.
-
-
- THE PROCEDURE SPECIFICATION
- _________________________________________________________________
-
- Lines 13, 14, and 15, give an example of a procedure specification.
- This is an incomplete procedure declaration that you will find
- useful when you begin writing larger programs. The procedure
- specification can be included for any procedure, if desired, and
- it describes the external interface to the procedure without
- declaring what the procedure actually does. The Pascal programmer
- will recognize this as being very similar to the forward
- declaration. More will be said about this topic later. Note that
- the procedure specification is not required in this case, it is
- only included as an illustration.
-
- Compile and run this program after you understand the simple
- addition and assignment that is done for purposes of illustration.
-
-
- PROCEDURES CALLING OTHER PROCEDURES
- _________________________________________________________________
-
- The example program CALLING.ADA contains examples of a procedure
- calling another procedure, which is perfectly legal if the called
- procedure is within the scope of the calling procedure. Much more
-
- Page 8-4
-
- Chapter 8 - Subprograms
-
- will be said about scope later in this tutorial. ===============
- The only rule that will be mentioned here is CALLING.ADA
- that the procedure must be defined prior to a ===============
- call to it. You should have no trouble
- understanding this program, and when you do, you
- should compile and execute it.
-
-
- HOW DO WE NEST PROCEDURES?
- _________________________________________________________________
-
- Examine the program named NESTING.ADA for ===============
- examples of nested procedures. We mentioned NESTING.ADA
- earlier that it was possible to embed a ===============
- procedure within the declarative part of any
- other procedure. This is illustrated in lines
- 10 through 21 where the procedure Second_Layer is embedded within
- the procedure Triple. In addition, the procedure Second_Layer has
- the procedure Bottom_Layer embedded within its declarative part in
- lines 12 through 15. Such nesting can continue indefinitely,
- because there is no limit to the depth of nesting allowed in Ada.
-
-
- VISIBILITY OF PROCEDURES
- _________________________________________________________________
-
- There is a limit on visibility of procedures. Any procedure is
- visible, and can therefore be called, if it is within the top level
- of the declarative part of the calling procedure. Any procedure
- is also visible if it is prior to, on the same level, and within
- the same declarative part as the calling point. Finally, any
- procedure can be called if it is prior to, on the same level, and
- within the same declarative part as any subprogram within which the
- calling point in nested. In simpler words, a procedure is visible
- in three cases. First, if it is within the declarative part of the
- calling procedure. The second case is if it is a peer (on the same
- level within a parent subprogram) or thirdly, if it is a peer of
- any parent.
-
- The procedure named Triple can therefore call Second_Layer, but not
- Bottom_Layer, since it is at a lower level and is not visible. The
- main program, according to these rules, is only allowed to call
- Triple, because the other two procedures are nested too deeply for
- a direct call. Be sure to compile and run this program and study
- the results.
-
-
- ADA FUNCTIONS
- _________________________________________________________________
-
- The program named FUNCT.ADA has two examples of Ada functions. A
- function differs from a procedure in only two ways. A function
- returns a single value which is used in the place of its call, and
- all formal parameters of a function must be of type in, with no
-
- Page 8-5
-
- Chapter 8 - Subprograms
-
- other mode permitted. In the program under ===============
- consideration, two functions are illustrated, FUNCT.ADA
- one beginning in line 16, and the other ===============
- beginning in line 21. Note that each begins
- with the reserved word function.
-
-
- A FUNCTION SPECIFICATION
- _________________________________________________________________
-
- In a manner similar to that defined for a procedure we can define
- a function specification that gives the interface of the function
- to the outside world. You will find the function specification
- useful later in your Ada programming efforts. It is similar to the
- Pascal forward declaration. Note once again, that the function
- specification is not required, it is only given here as an
- illustration.
-
- The function named Square requires one argument which it prefers
- to call Val, and which must be of type INTEGER. It returns a value
- to the main program which will be of type INTEGER because that is
- the type given between the reserved words return and is in the
- function body.
-
- A function must return a value, and the value is returned by
- following the reserved word return with the value to be returned.
- This return must be done in the executable part of the program, as
- illustrated in line 18. It is an error to fail to execute a return
- statement and fall through the end of a function. Such a runtime
- error will be reported by raising the exception Program_Error,
- which will be explained later in this tutorial.
-
-
- CAN YOU RETURN FROM A PROCEDURE?
- _________________________________________________________________
-
- It would be well to point out that you can return from a procedure
- by using the return statement also, but no value can be given since
- a procedure does not return a value in the same manner as a
- function. The return statement can be anyplace in the procedure
- or function and there can be multiple returns if the logic dictates
- the possibility of returning from several different places.
-
-
- A VALUE IS SUBSTITUTED FOR THE FUNCTION CALL
- _________________________________________________________________
-
- Examining the executable part of the program, we find that the
- variable Twelve is initialized to the value of 12, and this
- variable is used in line 28 as the argument for the function
- Square. This causes Square to be called, where the value of 12 is
- squared and the result is returned as 144. It is as if the
- resulting value of 144 replaces the function call Square(Twelve)
- in the Put procedure call, and the value of 144 is displayed.
-
- Page 8-6
-
- Chapter 8 - Subprograms
-
- Continuing on to line 30, the variable Twelve, which is still
- assigned the value of 12, and the constant 12, are given to the
- function Sum_Of_Numbers which returns the sum of 24. This value
- is assigned to the variable named Sum where it is stored for use
- in line 32.
-
- A function can be defined with no input parameters, in which case,
- the function is called with no parameters. Such a case would be
- useful for a random number generator where the call could be X :=
- Random; assuming a new random number is returned each time the
- function is called. Compile and execute this program and study the
- output generated.
-
-
- ANOTHER NOTE ABOUT THE DERIVED TYPE
- _________________________________________________________________
-
- As mentioned in chapter 6, a derived type with INTEGER as parent
- could be declared in line 14, and the derived type would inherit
- all operations available with INTEGER, including the ability to be
- used as the formal parameter for the function Square. This means
- that the function Square could be called with a variable of either
- of the two types. In order to do this, it is necessary to use a
- function specification so that the function body will follow the
- derived type declaration. Ada requires all smaller declarations
- to be made before subprogram bodies, so they do not get lost among
- the larger definitions.
-
-
- A FULLER EXAMPLE
- _________________________________________________________________
-
- Examine the program named ODDSQRE.ADA which is ===============
- a rather odd program that computes the square of ODDSQRE.ADA
- an integer type variable, but maintains the sign ===============
- of the variable. In this program, the odd
- square of 3 is 9, and the odd square of -3 is
- -9. Its real purpose is to illustrate several procedures and a
- function interacting.
-
- The main program named OddSqre has a function and a procedure
- nested within its declarative part, both of which have parameters
- passed. The nested procedure named Square_And_Keep_Sign has
- another procedure nested within its declarative part, named
- Do_A_Negative_Number which calls the function declared at the next
- higher level.
-
- This program is a terrible example of how to solve the problem at
- hand but is an excellent example of several interacting
- subprograms, and it would be profitable for you to spend enough
- time with it to thoroughly understand it.
-
-
-
-
- Page 8-7
-
- Chapter 8 - Subprograms
-
- COMMENTS ON ODDSQRE.ADA
- _________________________________________________________________
-
- This program illustrates some of the options that are purely
- programming taste. The first option is illustrated in line 24,
- where we could have chosen to use the construct Number_To_Square**2
- instead of the simple multiplication. Either form is correct and
- the one to be used should reflect the nature of the problem at
- hand. The second option is the fact that three returns were
- included in lines 39, 42, and 45, when a single return could have
- been used following the end of the if statement. This was done to
- illustrate multiple returns in use. In some cases, the logic of
- the program is much clearer to use several returns instead of only
- one. More than anything else, it is a matter of personal taste.
- Be sure to compile and execute this program.
-
-
- OVERLOADING
- _________________________________________________________________
-
- We have casually mentioned overloading earlier ================
- in this tutorial and it is now time to get a OVERLOAD.ADA
- good example of what overloading is by examining ================
- the program named OVERLOAD.ADA. This program
- includes two functions and two procedures and
- all four of these subprograms have the same name.
-
- The Ada system has the ability to discern which subprogram you wish
- to use by the types included in the actual parameter list and the
- type of the return. In line 48, we make a call to a function with
- a 2, which is an integer type constant, and we assign the returned
- value to an INTEGER type variable. The system will look for a
- function named Raise_To_Power with a single integer class formal
- parameter and an INTEGER type return which it finds in lines 14
- through 18, so it executes this function. The actual searching
- will be done at compile time so the efficiency is not degraded in
- any way by the overloaded names.
-
- If you continue studying this program you will see how the system
- can find the correct subprogram by comparing types used as formal
- parameters, and the type returned. Using the same name for several
- uses is referred to as overloading the subprogram names and is an
- important concept in the Ada language.
-
-
- OVERLOADING CAN CAUSE YOU PROBLEMS
- _________________________________________________________________
-
- If we made an error in this example program, by inadvertently
- omitting the decimal point in line 50, and assigning the result to
- an integer type variable, the system would simply use the wrong
- function and generate invalid data for us. An even worse problem
- could be found if we had a function that used an INTEGER for input
- and a FLOAT for output, because only one small error could cause
-
- Page 8-8
-
- Chapter 8 - Subprograms
-
- erroneous results. Because of this, it would be to your advantage
- to use different subprogram names for different operations, unless
- using the same names results in clear code.
-
- In the case of the text output procedures which we have been using,
- it makes a lot of sense to overload the output subprograms to avoid
- confusion. The name Put is used for outputting strings, integers,
- enumerated types, etc, and we are not confused. Overloading can
- be an advantage in certain cases but should not be abused just
- because it is available. Be sure to compile and execute this
- program.
-
-
- PROGRAMMING EXERCISES
- _________________________________________________________________
-
- 1. Rewrite TEMPCONV.ADA to do the temperature conversion in a
- procedure.
-
- 2. Rewrite TEMPCONV.ADA to do the temperature conversion in a
- function.
-
- 3. As mentioned in the text, add a function to the program
- OVERLOAD.ADA that uses an INTEGER for input and returns a
- FLOAT type result. Remove the decimal point from line 50 to
- see that the new function is called when we really intended
- to call the procedure with the floating point number.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 8-9