8 Subprograms


Overview

Sub programs, covering both procedures and functions, are the basis of all programs in Ada. Ada provides features which will be new to Pascal and C programmers. Overloading, named parameters, default parameter values, new parameter modes and return values of any type all make Ada sub programs significantly different.


Procedures

Procedures in Ada are similar to those in Pascal. A procedure can contain return statements.

Procedures are called in the normal Pascal style:


Functions

Functions are very similar to procedures except that they also return a value to the calling sub program. The use of return statements is very similar to C. Functions can have as many return statements as required. A function returning a variable of a given type can be used anywhere a variable of that type can be used.


Subprograms in general

Ada has been designed with separate compilation very much in mind. To this end we can produce just a specification of a subprogram and submit this to the compiler. Once compiled and the description stored in an attribute file, it can be checked for compatibility with other procedures (and packages) when they are compiled. By producing a large number of procedure stubs we can pre test the design of a system and pick up any design errors before any more work is done.

A procedure specification for the above procedure would be:

If we wish to use a seperately compiled subprogram we can with it in another subprogram.

A function specification may appear as:

Like Pascal and unlike C, a subprogram can contain nested subprograms within them that are not visible outside the subprogram.


Parameter modes

Ada provides three parameter modes for procedures and functions.

o in

o in out

o out

These modes do not correspond directly to any modes in other languages, they will be discussed below. The following should be noted.

o All parameters to subprograms are by default in.

The parameter passing mechanism is by copy-in, copy-out for in/out scalars. The language specifies that any other types can be passed by copy-in/copy-out, or by reference.

Ada95 mandates that limited private types (see later) are passed by reference, to avoid problems with the breaking of privacy.


In mode

Parameters supplied with this mode are like value parameters in Pascal, and normal parameters in C with the exception that they cannot be assigned a value inside the subprogram. The formal parameter (that in the sub program) is a constant and permits only reading of the value of the associated actual parameter.


In out mode

This mode corresponds directly to the var parameters of Pascal. Actual parameters can be used on either the left or the right hand side of statements in procedures. These parameters are effectively read/write.


Out mode

The formal parameter is a variable and may be assigned values, however it's initial value is not necessarily defined, and should not be relied upon.

Caution - out mode parameters that aren't initialized!

Here if the target is not found, then if position is not assigned a value, the copy out parameter mode causes the unitialised value to be placed into the awaiting actual parameter, the associated range check may cause a constraint error.

E.g.

If result = false, a constraint error may be generated when the procedure returns.


Named parameters

Normally the association between the formal (defined in the sub program specification) and actual parameters (supplied in the sub program call) is on a one to one basis i.e. it is positional. The first formal parameter is associated with the first actual parameter, etc.

To enhance the readability of sub program calls (Ada is designed to be readable) we can associate the name of the formal parameter and the actual parameter. This feature makes sub program calls immensely more readable.

Lining up the parameters vertically can also be an aid to readability.

Because the association is made explicit (instead of the implicit association with positional parameters) there is no need to supply them in the same order as in the sub program specification. There is no restriction on the order in which named parameters are written.


Mixing positional and named parameters

Positional parameters and named parameters can be mixed with the one proviso:
positional parameters must precede the named parameters.

could be called in the following manners:


Default parameter values

A default value can be be given for any in parameters in the procedure specification. The expression syntax is the same as that for pre initialised variables and is:

This assigns a value for no_of_lines if the procedure is called without a corresponding parameter (either positional or named).

E.g. the procedure could be called as

Similarly if a procedure write_lines was defined as

then it could be called as


Local subprograms

So far the subprograms presented have all been independent compilation units. It is possible to embed subprograms in another subprogram such that only one compilation unit is constructed. These local subprograms can only be referenced from the surrounding subprogram. This is identical to the features provided by Pascal.

In this example the scope of procedure display_values is limited to inside the procedure ive_got_a_procedure - it can't be 'seen' or called from anywhere else.


Separate compilation

In the previous example if any change is made to any of the code then both procedures must be resubmitted to the compiler (because they are in the one source file). We can separate the two components into seperate files while still retaining the limited scope of procedure display_values. This is a little like the #include directive in C, but the files are now independent compilation units.

In the first file...

In the second file...

Apart from being in another file (and being a seperate compilation unit) the code is identical in all respects to the previous version. However if the inner subprograms change then only they have to be submitted to the compiler. This also allows a program to be broken up into several pieces, which can ease the job of understanding it.


Overloading

Finding new names for functions that do the same thing to variables of different types is always a problem. The procedure insert is a good example. To give programmers a bit more breathing space, Ada allows sub programs to have the same name, it only insists that they are distinguishable. This is called overloading.


Subprogram overloading

Two sub programs with the same name are distinguishable if their profile is different. The profile consists of the number of parameters, thier type and, if it is a function, the return type.

So long as the compiler can tell which sub program you requested by matching the profile of the call to the specifications of the sub programs you have supplied, it's happy; otherwise you'll get an ambiguous reference error.

The procedures Put and Get in the package Ada.Text_IO are examples of overloaded subprograms.


Operator overloading

In languages such as Pascal the + operator is overloaded. Sometimes it is used to add integers, sometimes reals, sometimes strings. It is quite obvious that this one operator is used to represent very different code.

Ada allows programmers to overload operators with thier own code. One restriction on this overloading of the operator name, is as expected, that the functions are distinguishable from the originals supplied, i.e. its profile is unique. Even this problem can be overcome by specifying the package name (see the next section).

Overloaded operators cannot be seperate compilation units. - they must be contained in another unit such as a procedure, function or package.

Consider an example where we wish to provide facilities to add two vectors together.

This example uses most features discussed in the last few chapters.


to the index...