Previous | Next | Table of Contents | Index | Program List | Copyright

4.7 System Structures: Writing Simple Functions

In Section 3.6, you saw how to use some predefined functions in a package, the Month, Day, and Year functions in the standard package Ada.Calendar; in the previous section you saw how to use the square root function from another standard package, Ada.Numerics.Elementary_Functions. This section introduces the very important subject of how to write such functions; the next section shows how to put functions in packages for yourself and others to use again later.

Function Specifications

In general, a function is written so as to require the caller to supply some values to it. When called, the function performs its desired computation and then returns a result to the calling program. The line indicating the name of the function, the list of expected parameters, and the type of the returned result is called a function specification or sometimes function declaration. You saw three such specifications in Chapter 3:

    FUNCTION Year (Date: Time) RETURN Year_Number;
    FUNCTION Month (Date: Time) RETURN Month_Number;
    FUNCTION Day (Date: Time) RETURN Day_Number;

The specification for Year tells the compiler--and the reader--that this function must be called with one value of type Time and that it returns a result of type Year_Number to the program that calls it. The other two specifications are similar.

Here is a specification for a function to find the larger of two integer values and return it to the calling program:

    FUNCTION Maximum(Value1, Value2: Integer) RETURN Integer;
Notice that between the parentheses is a list of the expected parameters and that after the word RETURN is the type of the returned result. In this case, the function is to determine which of the two parameters is larger and return it as the result.

Calling a Function

Recall from Chapter 3 that we were able to extract the year from a system-generated time value by writing

    This_Year := Calendar.Year(Date => Right_Now);

where This_Year was declared as a variable of type Calendar.Year_Number and Right_Now was a variable of type Calendar.Time. Notice that between the parentheses is an association of the name of the formal parameter (Date) with the variable containing the value of the actual parameter (Right_Now).

How could we use our function Maximum in a similar way? Given an integer variable Larger, writing

    Larger := Maximum(Value1=>24,Value2=>-57);
stores the value 24 in the variable Larger because that is the larger of the two values. Given two integer variables Grade1 and Grade2, writing
    Grade1 := -24;
    Grade2 := 113;
    Larger := Maximum(Value1=>Grade1,Value2=>Grade2);

stores in Larger the value 113, again because that is the larger value. Notice again how the formal parameters Value1 and Value2 are associated with the actual parameters Grade1 and Grade2, and notice that it is improper to write, for example,

 
    Larger := Maximum(Grade1=>Value1,Grade2=>Value2);

because Value1 is the formal parameter and Grade1 is the actual. The formal parameter comes first, followed by the actual parameter.

The difference between these two examples is that the fuction Year already exists (in package Calendar) but the function Maximum does not. We have a specification indicating the name of the function, how it is to be called, and what it returns, but we do not yet actually have a function that will find the larger number.

Function Bodies

To complete our function Maximum we need to write a function body, that is, a small program in Ada in a form that the compiler will recognize as a function. Here is the desired function body:

    FUNCTION Maximum (Value1, Value2: Integer) RETURN Integer IS
        Result: Integer;
    BEGIN
        IF Value1 > Value2 THEN
        	Result := Value1;
        ELSE
    	    Result := Value2;
        END IF;
        RETURN Result;
    END Maximum;

This function body has the basic form of an Ada program. There is a header line similar to the first line of a program; this line ends with the word IS. Next there is a section of declarations; here we are declaring only a single program variable Result. Following the word BEGIN is the statement sequence of the function body, and the function body ends with an END. The IF statement in the function body stores in the variable Result the larger of Value1 and Value2. Finally, the value in Result is returned to the calling program as the function result. This value can be stored directly in a variable of the calling program, as in the examples above, or used as part of an expression implementing a larger calculation.

The variable Result is called a local variable of the function. Because it is declared inside the function body, it has no existence outside the function body. It is good practice when writing a function to put the variables needed by the function inside the function body so that they are the private property of the function and cannot be seen or disturbed by any other program.

To see an example of how a function is declared as part of a larger program, consider Program 4.6, in which the user is prompted to enter two integer values FirstValue and SecondValue. These values are then passed to the function Maximum, which returns the larger value to the main program. The answer is then displayed. The function Maximum is declared in the declaration part of the main program.

Program 4.6
Finding the Larger of Two Integer Values with a Function

WITH Ada.Text_IO;
WITH Ada.Integer_Text_IO;
PROCEDURE Max_Two IS
------------------------------------------------------------------------
--| Finds the larger of two integer values
--| using the Maximum function
--| Author: Michael B. Feldman, The George Washington University
--| Last Modified: July 1995
------------------------------------------------------------------------
 
  FirstValue:  Integer;
  SecondValue: Integer;
  Larger:      Integer;

  -- function specification
  FUNCTION Maximum (Value1, Value2: Integer) RETURN Integer;

  -- function body
  FUNCTION Maximum (Value1, Value2: Integer) RETURN Integer IS
    Result: Integer;
  BEGIN
    IF Value1 > Value2 THEN
      Result := Value1;
    ELSE
      Result := Value2;
    END IF;
    RETURN Result;
  END Maximum;

BEGIN

  Ada.Text_IO.Put (Item => "Please enter first integer value  > ");
  Ada.Integer_Text_IO.Get (Item => FirstValue);
  Ada.Text_IO.Put (Item => "Please enter second integer value > ");
  Ada.Integer_Text_IO.Get (Item => SecondValue);

  Larger := Maximum(Value1=>FirstValue, Value2=>SecondValue);

  Ada.Text_IO.Put (Item => "The larger number is ");
  Ada.Integer_Text_IO.Put (Item => Larger, Width => 1);
  Ada.Text_IO.New_Line;

END Max_Two;
Sample Run
Please enter first integer value  > 374
Please enter second integer value > -158
The larger number is 374

SYNTAX DISPLAY
Function Specification

Form:
FUNCTION fname ( formal parameters ) RETURN result
type ;

Example:
FUNCTION Square (Num : Integer) RETURN Integer;

Interpretation:
The function fname is declared. The list of formal parameters is enclosed in parentheses. The data type of the function result is indicated by the identifier result type.

SYNTAX DISPLAY
Function Body

Form:
FUNCTION fname ( formal parameters ) RETURN result type IS
 	local declaration section 
BEGIN
 	statement sequence
END fname;

Example:
FUNCTION Square (Num : Integer) RETURN Integer IS
    Result: Integer;
BEGIN
    Result := Num * Num;
    RETURN Result;
END Square;

Interpretation:
The function fname is declared. The list of formal parameters is enclosed in parentheses. The data type of the function result is indicated by the identifier result type. Any identifiers declared in the local declaration section exist only during the execution of the function. The function body describes the data manipulation to be performed by the function. At least one RETURN statement must be executed each time the function is called.

Note 1:
The result type is not restricted in Ada. It may be any type.

Note 2:
If there are no parameters, you should omit the formal parameters and parentheses.

Note 3:
The first line of the function body must agree exactly with the function specification, except that the specification ends with a semicolon and the first line of the body ends with IS. In fact, the way the line ends indicates to the compiler whether it should treat the line as a specification or as the first line of a body. It is therefore important not to confuse the two endings, lest you confuse the compiler.


Previous | Next | Table of Contents | Index | Program List | Copyright

Copyright © 1996 by Addison-Wesley Publishing Company, Inc.