In this book you have been using calls to procedures provided by the standard
input/output libraries and another package called Screen
. In this
section you will learn how to write procedures.
Procedures and functions are both subprograms, but they differ in two important ways. First, a procedure is called with a procedure call statement, as in
Ada.Float_Text_IO.Put (Item => X, Fore => 3, Aft => 2, Exp => 0);whereas a function is used in an expression, for example,
Temp := UsefulFunctions.Minimum (Value1 => X, Value2 => Y) + 45;A function returns a result so that the result can be used in an expression; a procedure does not return a result.
The second important difference is that a function is permitted to have parameters that are passed only into the function, whereas a procedure is allowed to have parameters of three kinds, or modes:
IN
parameters--These are passed into the
procedure and, inside the procedure, are treated as constants and may not be
changed (e.g., they may not appear on the left side of an assignment statement).
OUT
parameters--These are computed in the
procedure and passed out to the caller.[1
]
IN OUT
parameters--These are passed into
the procedure, possibly changed by it, and passed back out
again.
The determination of a particular parameter's mode is based on the direction
of the data flow between the procedure and its calling programs. If the
parameter is used to transmit data to the procedure, its mode should be
IN
; if the parameter receives data from the procedure, its
mode should be OUT
.
Mode IN
parameters are similar to the parameters of a function
and are used to transmit values that will not be changed by the procedure, only
used by it. For example, the parameters to the various Put
procedures provided by Ada.Text_IO
are IN
parameters,
because the data and formatting values are transmitted from the caller to the
procedure.
Mode OUT
parameters are commonly used in input routines like
the Get
operations in Ada.Text_IO
. It may seem
strange that an input routine should have an OUT
parameter,
but the input routine receives a value from the terminal or a file and passes
it out to the program that calls it. The caller receives the input value
from the procedure.
Mode IN OUT
parameters are used when a procedure will modify
its parameters. An example follows.
Example 6.12
Here is a procedure specification for a procedure Order
,
which orders the values in the two variables whose names are supplied to it as
actual parameters, placing the smaller of the two values in X
and
the larger in Y
:
PROCEDURE Order (X: IN OUT Float; Y: IN OUT Float);
A procedure call statement
Order (X => Num1, Y => Num2);
is intended to order the values in the two floating-point
variables Num1
and Num2
. Suppose, for example, that
Num1
is 3.0 and Num2
is -5.0. After the above call we
want Num1
to be -5.0 and Num2
to be 3.0. Ordering
pairs of values is a very common operation in programming, especially in
sorting applications. Here is the body of procedure Order
:
PROCEDURE Order (X: IN OUT Float; Y: IN OUT Float) IS -- Pre: X and Y are assigned values -- Post: X has the smaller value and Y has the larger value Temp: Float; BEGIN IF X > Y THEN -- interchange the values of X and Y Temp := X; X := Y; Y := Temp; END IF; END Order;
The variable Temp
is a local variable of the
procedure, necessary to carry out the interchange. Temp
is created
when the procedure is called; it is destroyed when the procedure returns to its
caller. X and Y
must be IN OUT
parameters because
their values are changed by the procedure. The effect of calling procedure
Order
is shown in
Program
6.9, which carries out a very simple sort of three numbers
Num1
, Num2
, and Num3
by calling
Order
three times:
Order (X => Num1, Y => Num2); Order (X => Num1, Y => Num3); Order (X => Num2, Y => Num3);
Because each statement contains a different association of
actual parameters with the formal parameters X
and
Y
, a different pair of variables is ordered each time the
procedure is called.
Figure
6.1 shows a structure chart for this program.
Program 6.9
WITH Ada.Text_IO; WITH Ada.Float_Text_IO; PROCEDURE Sort_3_Numbers IS ------------------------------------------------------------------------ --| Reads three numbers and sorts them --| so that they are in increasing order. --| Author: Michael B. Feldman, The George Washington University --| Last Modified: July 1995 ------------------------------------------------------------------------ Num1 : Float; -- a list of three cells Num2 : Float; Num3 : Float; -- procedure specification PROCEDURE Order (X: IN OUT Float; Y: IN OUT Float); -- procedure body PROCEDURE Order (X: IN OUT Float; Y: IN OUT Float) IS -- Pre: X and Y are assigned values. -- Post: X has the smaller value and Y has the larger value. Temp : Float; -- copy of number originally in X BEGIN -- Order IF X > Y THEN -- interchange the values of X and Y Temp := X; -- Store old X in Temp X := Y; -- Store old Y in X Y := Temp; -- Store old X in Y END IF; END Order; BEGIN -- Sort_3_Numbers Ada.Text_IO.Put (Item => "Enter 3 float numbers to be sorted, one per line."); Ada.Text_IO.New_Line; Ada.Float_Text_IO.Get(Item => Num1); Ada.Float_Text_IO.Get(Item => Num2); Ada.Float_Text_IO.Get(Item => Num3); -- Sort the numbers Order (X => Num1, Y => Num2); -- Order the data in Num1 and Num2 Order (X => Num1, Y => Num3); -- Order the data in Num1 and Num3 Order (X => Num2, Y => Num3); -- Order the data in Num2 and Num3 -- Display the results. Ada.Text_IO.Put(Item => "The three numbers in order are: "); Ada.Float_Text_IO.Put(Item => Num1, Fore => 5, Aft => 2, Exp => 0); Ada.Float_Text_IO.Put(Item => Num2, Fore => 5, Aft => 2, Exp => 0); Ada.Float_Text_IO.Put(Item => Num3, Fore => 5, Aft => 2, Exp => 0); Ada.Text_IO.New_Line; END Sort_3_Numbers;Sample Run
Enter 3 float numbers to be sorted, one per line. 23.7 -99.4 1.78 The three numbers in order are: -99.40 1.78 23.70
Figure 6.1.
Structure Chart for Simple Sort Program
To show the importance of the choice of parameter mode for procedure
Order
, Fig. 6.2 gives a compilation listing for a modification of
the procedure, with the parameter modes changed from IN OUT
to
IN
. Notice that the Ada compiler has marked as errors the lines in
which attempts are made to change the IN
parameters.
Figure 6.2
Procedure Order with Compilation Errors
NYU GNAT Compiler Version 2.06 (C) Copyright NYU, 1992,1993,1994,1995 Compiling: order.adb last modified at 95-07-25 21:02.21 GMT. 1. PROCEDURE Order (X: IN Float; Y: IN Float) IS 2. -- Pre: X and Y are assigned values. 3. -- Post: X has the smaller value and Y has the larger value. 4. 5. Temp : Float; -- copy of number originally in X 6. 7. BEGIN -- Order 8. 9. IF X > Y THEN 10. -- interchange the values of X and Y 11. Temp := X; -- Store old X in Temp 12. X := Y; -- Store old Y in X | >>> assignment to "IN" mode parameter not allowed 13. Y := Temp; -- Store old X in Y | >>> assignment to "IN" mode parameter not allowed 14. END IF; 15. 16. END Order;
Figure 6.3 shows the data areas for the main
program and procedure
Order
immediately after the execution of the procedure call
statement
Order(X => Num1, Y => Num2); -- Order the data in Num1 and Num2
This diagram shows the data values read into Num1
,
Num2
, and Num3
. It also shows that the local
variable Temp
is considered undefined immediately after the
procedure is called.
Figure 6.3 also shows the parameter correspondence specified by the actual
parameter list above. The double-headed arrows symbolize the connection between
formal parameters X
and Y
and main program variables
Num1
and Num2
, respectively. Whenever X
is referenced in the procedure, the data in variable Num1
are
actually manipulated.
Figure 6.3
Parameter Correspondence for Order (Num1, Num2)
The execution of the procedure is traced in Table 6.1. The actual parameter
represented by each formal parameter is shown in parentheses at the top of the
table. Because the value of Num1
is less than that of
Num2
, the true alternative is skipped and the variable values are
unchanged.
Table 6.1
Trace of Procedure Execution for Order (Num1, Num2)
Statement in Order X (Num1) Y (Num3) Temp Effect 8.0 10.0 ? IF X > Y THEN 8.0 > 10.0 is false; do nothing
The parameter correspondence specified by the procedure call statement
Order (X => Num1, X => Num3);
is pictured in Fig. 6.4. This time parameter
X
corresponds to variable Num1
and parameter Y
corresponds to variable Num3
. This means that whenever formal
parameter Y
is referenced in the procedure, the data in main
program variable Num3
are actually manipulated.
Figure 6.4
Parameter Correspondence for Order (Num1, Num3)
This second execution of the procedure is traced in Table 6.2. The actual
parameter represented by each formal parameter is shown in parentheses at the
top of the table. The procedure execution switches the values stored in main
program variables Num1
and Num3
, as desired.
Table 6.2
Trace of Procedure Execution for Order (Num1, Num3)
Statement in Order X (Num1) Y (Num3) Temp Effect 8.0 6.0 ? IF X > Y THEN 8.0 > 6.0 is true Temp := X; 8.0 save old Num1 in Temp; X := Y; 6.0 save old Num3 in Num1; Y := Temp; 8.0 save Temp in Num3.
Each time a procedure call statement is executed, an area of memory is allocated for storage of that procedure's data. Included in the procedure data area are storage cells for any local variables or constants that may be declared in the procedure. The procedure data area is always erased when the procedure terminates, and it is recreated (with all values undefined) when the procedure is called again.
Memory cells are allocated in the procedure data area for each formal parameter. These cells are used in different ways for parameters of the three modes:
IN
parameter, the value of the corresponding
actual parameter is copied into this cell when the procedure is called. The
compiler will not permit a statement within the procedure to change the value
in this cell.
OUT
parameter, the local cell is initially
undefined; the procedure computes a value and saves it in this memory cell.
After the procedure completes its work, just before it returns to its calling
program, the value in the local cell is copied back into the actual parameter
in the calling program.
IN OUT
parameter, the behavior is a combination of
the other two. The actual value is copied into the local cell when the
procedure is called. Statements of the procedure may change the value in the
local cell. Just before the procedure returns to its caller, the value in the
local cell is copied back into the actual parameter in the calling program.
We note that these rules apply to parameters of scalar type, which
are the only kind we have studied so far. Beginning in Chapter 8, you will see
that parameter-passing behavior may differ somewhat for parameters of
structured type. Also, parameters are passed to a function's data area,
just as they are to a procedure's; recall, though, that function parameters in
Ada can have mode IN
parameters only; mode OUT
and
IN OUT
parameters are not permitted.
Syntax Rules for Parameter Lists
This section presents the syntax rules for procedure declarations and procedure call statements with parameters. The displays that follow summarize these rules.
SYNTAX DISPLAY
Procedure Specification (Procedure with Parameters)
PROCEDURE pname (formal-parameters);
PROCEDURE Highlight (Ch : IN Character);
SYNTAX DISPLAY
Procedure Body (Procedure with Parameters)
PROCEDURE pname (formal-parameters) IS local declaration-section BEGIN statement sequence END pname;
PROCEDURE Highlight (Ch : IN Character) IS Border CONSTANT Character := '*'; BEGIN Ada.Text_IO.Put (Item => Border); Ada.Text_IO.Put (Item => Ch); Ada.Text_IO.Put (Item => Border); END Highlight;
The statement sequence describes the data manipulation to be performed by the procedure. The formal parameter names are used in place of the actual parameter names in this description.
SYNTAX DISPLAY
Procedure Call Statement (Procedure with Parameters)
pname (actual-parameters)
Highlight (Ch => 'A')
The formal parameter list determines the form of any actual parameter list that may be used to call the procedure. This form is determined during the translation of the program when the compiler processes the procedure declaration.
Later, when a procedure call statement is reached, the compiler checks the actual parameter list for consistency with the formal parameter list. An actual parameter list may be a list of expressions, variables, or constants separated by commas. The actual parameter list must satisfy the rules shown below.
OUT
and IN OUT
parameters, an actual
parameter must be a variable. For mode IN
parameters, an actual
parameter may be a variable, constant, or expression.
PROGRAM STYLE
Named Association in Actual Parameter Lists
=>
). This naming is optional in Ada; if it is used, the
order of the actual parameters does not, strictly speaking, have to
match the order of the formal parameters. It is good practice to use named
association and also to list the actual parameters in an order corresponding to
the order of the formal parameters. In this way, no confusion arises for the
reader of the program as to which actual parameter matches which formal
parameter.
Copyright © 1996 by Addison-Wesley Publishing Company, Inc.