In Section 4.8 we showed how to write a simple package, Min_Max, containing functions to find the minimum and maximum of two integer values. Let us rework that package to include two more useful mathematical functions, the sum of integers from 1 to N and the product of integers from 1 to N. The latter function is called factorial.
First we shall rewrite the package specification to name the package
Useful_Functions
and include specifications for the two new
functions. Note in the specification that the sum and factorial functions
require parameters of type Positive
and return
Positive
results.
Program
5.18 shows the package specification.
Program 5.18
Specification for Package Useful_Functions
PACKAGE Useful_Functions IS ------------------------------------------------------------------------ --| Specifications of functions provided by Useful_Functions package --| Author: Michael B. Feldman, The George Washington University --| Last Modified: July 1995 ------------------------------------------------------------------------ FUNCTION Minimum (Value1: Integer; Value2: Integer) RETURN Integer; FUNCTION Minimum (Value1: Float; Value2: Float) RETURN Float; -- Pre: Value1 and Value2 have been assigned values -- Post: Returns the smaller of the two input values FUNCTION Maximum (Value1: Integer; Value2: Integer) RETURN Integer; FUNCTION Maximum (Value1: Float; Value2: Float) RETURN Float; -- Pre: Value1 and Value2 have been assigned values -- Post: Returns the larger of the two input values FUNCTION Sum (N: Positive) RETURN Positive; -- Pre: N has been assigned a value -- Post: Returns the sum of integers from 1 to N FUNCTION Factorial (N: Positive) RETURN Positive; -- Pre: N has been assigned a value -- Post: Returns the product of integers from 1 to N END Useful_Functions;
Minimum
and two functions called Maximum
.
Looking at the two Minimum
functions,
FUNCTION Minimum (Value1, Value2: Integer) RETURN Integer; FUNCTION Minimum (Value1, Value2: Float) RETURN Float;we see that they have the same names but different parameter profiles; that is, their input parameters and return types are different. This is an example of overloading, which in Ada allows two or more different operations to have the same name, as long as there is enough difference in their parameter profiles so that the compiler can distinguish them.
The advantage of overloading is that operations with similar behavior or
functionality can be given similar names. This makes programs easier to write
and to read because the programmer is not forced to invent names like
MinimumInteger
and MinimumFloat
merely because the
language requires all subprograms to have distinct names.
Actually, you have been using overloaded operations without realizing it. One example relates to the input/output libraries. Many programs in this book have used procedure calls of the form
Ada.Integer_Text_IO.Get (Item => CurrentValue);from the input/output package for integer tokens. On the other hand, in Program 5.6, a procedure call appears
Ada.Integer_Text_IO.Get (File => TestScores, Item => CurrentValue);which has the same name,
Get
, but a different parameter profile: The
second procedure call includes a file variable; the first does not. There is no
"magic" about this, or anything unique to the I/O libraries--it is just an
application of the overloading principle.
When the compiler reaches a statement like one of the two above, it can select the appropriate procedure to include in the executable program by examining the parameter profile. If the profile matches one of the procedures made available by context clauses, all is well. If there is no match, a compilation error results. It could be that there are two matches; this case also results in a compilation error.
Another example comes from the arithmetic operations we have been doing. An assignment statement such as
Result := Result + Count;uses a different
+
depending on whether its operands are
Integer
or Float
. Indeed, the machine instructions
generated by the compiler are quite different for the two numeric types. We
could write specifications for the integer and float versions of +
that look just like function specifications:
FUNCTION "+" (Left: Integer; Right: Integer) RETURN Integer; FUNCTION "+" (Left: Float; Right: Float ) RETURN Float;
Mathematically,
an arithmetic operation is just a special kind of function; writing an operator
specification this way just reflects that mathematical fact. There is no
problem in naming both of the operations +
(the quotes are
required in this form for syntactic reasons): They have different parameter
profiles, so the compiler can distinguish between them.
Specifications of all the predefined types and operators in Ada
appear in the Language Reference Manual in a section called PACKAGE
Standard
; a version of this very useful description appears in Appendix
C. PACKAGE Standard
is automatically available to all Ada
programs; no context clause is necessary. When the compiler reaches a statement
like
Result := Result + Count;it examines the types of
Result
and Count
to discover
whether a matching +
is available. If Result
is
integer and Count
is float, for example, there is no matching
+
in PACKAGE Standard
, so a compilation error arises.
PROGRAM STYLE
Using Overloading Wisely
The next step is to provide the package body of Useful_Functions
,
which consists of function bodies for the six functions. The body of
Sum
is adapted from Program 5.3; the body of
Factorial
can be readily adapted from the body of
Sum
. (note, however, that Result
is initialized to 1,
not 0). The complete package body appears in
Program
5.19.
Program 5.19
PACKAGE BODY Useful_Functions IS ------------------------------------------------------------------------ --| Body of Useful_Functions package --| Author: Michael B. Feldman, The George Washington University --| Last Modified: July 1995 ------------------------------------------------------------------------ -- minimum of two Integer values FUNCTION Minimum (Value1: Integer; Value2: Integer) RETURN Integer IS Result: Integer; BEGIN -- Minimum IF Value1 < Value2 THEN Result := Value1; ELSE Result := Value2; END IF; RETURN Result; END Minimum; -- minimum of two Float values FUNCTION Minimum (Value1: Float; Value2: Float) RETURN Float IS Result: Float; BEGIN -- Minimum IF Value1 < Value2 THEN Result := Value1; ELSE Result := Value2; END IF; RETURN Result; END Minimum; -- maximum of two Integer values FUNCTION Maximum (Value1: Integer; Value2: Integer) RETURN Integer IS Result: Integer; BEGIN -- Maximum IF Value1 > Value2 THEN Result := Value1; ELSE Result := Value2; END IF; RETURN Result; END Maximum; -- maximum of two Float values FUNCTION Maximum (Value1: Float; Value2: Float) RETURN Float IS Result: Float; BEGIN -- Maximum IF Value1 > Value2 THEN Result := Value1; ELSE Result := Value2; END IF; RETURN Result; END Maximum; -- sum of integers from 1 to N FUNCTION Sum (N: Positive) RETURN Positive IS Result: Natural; BEGIN -- Sum Result := 0; FOR Count IN 1..N LOOP Result := Result + Count; END LOOP; RETURN Result; END Sum; -- factorial, or product of integers from 1 to N FUNCTION Factorial (N: Positive) RETURN Positive IS Result: Positive; BEGIN -- Factorial Result := 1; FOR Count IN 1..N LOOP Result := Result * Count; END LOOP; RETURN Result; END Factorial; END Useful_Functions;Program 5.20 illustrates the overloading principle in action by finding the maximum of two integers and the maximum of two floats. Notice in this program that
Useful_Functions.Maximum
appears to be called twice. In fact,
different functions are being called, as you can see from the different
parameter profiles: In the first call integers are supplied; in the second call
floats are supplied.
Program 5.20
WITH Ada.Text_IO; WITH Ada.Integer_Text_IO; WITH Ada.Float_Text_IO; WITH Useful_Functions; PROCEDURE Max_Int_Flt IS ------------------------------------------------------------------------ --| Illustrates the overloading principle using the Maximum --| functions for both integer and float quantities --| Author: Michael B. Feldman, The George Washington University --| Last Modified: July 1995 ------------------------------------------------------------------------ Int1 : Integer; -- inputs Int2 : Integer; LargerInt : Integer; -- output Flt1 : Float; -- inputs Flt2 : Float; LargerFlt : Float; -- output BEGIN -- Max_Int_Flt Ada.Text_IO.Put (Item => "Please enter first integer value > "); Ada.Integer_Text_IO.Get (Item => Int1); Ada.Text_IO.Put (Item => "Please enter second integer value > "); Ada.Integer_Text_IO.Get (Item => Int2); LargerInt := Useful_Functions.Maximum(Value1=>Int1, Value2=>Int2); Ada.Text_IO.Put (Item => "The larger integer is "); Ada.Integer_Text_IO.Put (Item => LargerInt, Width => 1); Ada.Text_IO.New_Line; Ada.Text_IO.Put (Item => "Please enter first float value > "); Ada.Float_Text_IO.Get (Item => Flt1); Ada.Text_IO.Put (Item => "Please enter second float value > "); Ada.Float_Text_IO.Get (Item => Flt2); LargerFlt := Useful_Functions.Maximum(Value1=>Flt1, Value2=>Flt2); Ada.Text_IO.Put (Item => "The larger float is "); Ada.Float_Text_IO.Put (Item => LargerFlt, Fore => 1, Aft => 2, Exp => 0); Ada.Text_IO.New_Line; END Max_Int_Flt;Sample Run
Please enter first integer value > -27 Please enter second integer value > 34 The larger integer is 34 Please enter first float value > 29.77 Please enter second float value > 15.09 The larger float is 29.77Finally, Program 5.21 gives a program that prompts the user for an integer between 1 and 10, then displays a table of the sum and factorial of each of the integers from 1 to the number entered.
Program 5.21
WITH Ada.Text_IO; WITH Ada.Integer_Text_IO; WITH Useful_Functions; PROCEDURE Sum_and_Factorial IS ------------------------------------------------------------------------ --| Prompts the user for an integer N from 1 to 10 --| and displays the sum and factorial of all integers from --| 1 to N. Sum and Factorial are gotten from Useful_Functions. . --| Author: Michael B. Feldman, The George Washington University --| Last Modified: July 1995 ------------------------------------------------------------------------ SUBTYPE OneToTen IS Positive RANGE 1..10; MaxNum: OneToTen; -- input - a value from 1-10 SumToCount: Positive; -- output - sum of integers from 1-Count ProdToCount: Positive; -- output - product of integers from 1-Count BEGIN -- Sum_and_Factorial Ada.Text_IO.Put (Item => "Please enter an integer from 1 to 10 > "); Ada.Integer_Text_IO.Get (Item => MaxNum); Ada.Text_IO.New_Line; Ada.Text_IO.Put(Item => " N Sum Factorial"); Ada.Text_IO.New_Line; Ada.Text_IO.Put(Item => " ----------------------"); Ada.Text_IO.New_Line; FOR Count IN 1..MaxNum LOOP SumToCount := Useful_Functions.Sum (N => Count); ProdToCount := Useful_Functions.Factorial (N => Count); Ada.Integer_Text_IO.Put (Item => Count, Width => 3); Ada.Integer_Text_IO.Put (Item => SumToCount, Width => 7); Ada.Integer_Text_IO.Put (Item => ProdToCount, Width => 9); Ada.Text_IO.New_Line; END LOOP; END Sum_and_Factorial;Sample Run
Please enter an integer from 1 to 10 > 9 N Sum Factorial ---------------------------- 1 1 1 2 3 2 3 6 6 4 10 24 5 15 120 6 21 720 7 28 5040 8 36 40320 9 45 362880
PROGRAM STYLE
Displaying a Table
Ada.Text_IO.Put (Item => " N Sum Factorial"); Ada.Text_IO.New_Line; Ada.Text_IO.Put (Item => " ---------------------"); Ada.Text_IO.New_Line;
The
spaces in the first string are used to align the column headings over their
respective table values. We have left enough spaces to center the column titles
of the respective values. The second string is used to "draw a line" between
the column titles and the values. Within the FOR
loop, the four
statements
Ada.Integer_Text_IO.Put (Item => Count, Width => 3); Ada.Integer_Text_IO.Put (Item => SumToCount, Width => 7); Ada.Integer_Text_IO.Put (Item => ProdToCount, Width => 9); Ada.Text_IO.New_Line;display three output values on each line of the table, using 19 columns per line.
Copyright © 1996 by Addison-Wesley Publishing Company, Inc.