0% found this document useful (0 votes)
8 views7 pages

Ada Programming Subprograms

The document provides an overview of subprograms in Ada programming, categorizing them into procedures and functions, and detailing their parameter modes: in, in out, and out. It explains how procedures do not return values while functions do, and discusses named and default parameters, as well as the ability to rename subprograms. Additionally, it covers the rules for parameter passing and the importance of return statements in functions.

Uploaded by

turing1946
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views7 pages

Ada Programming Subprograms

The document provides an overview of subprograms in Ada programming, categorizing them into procedures and functions, and detailing their parameter modes: in, in out, and out. It explains how procedures do not return values while functions do, and discusses named and default parameters, as well as the ability to rename subprograms. Additionally, it covers the rules for parameter passing and the importance of return statements in functions.

Uploaded by

turing1946
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Ada Programming/Subprograms

Computing » Computer Science » Computer Programming » Ada Programming

Contents
Procedures
Functions
Named parameters
Default parameters
Renaming
See also
Wikibook
Ada 95 Reference Manual
Ada 2005 Reference Manual
Ada Quality and Style Guide

In Ada the subprograms are classified into two categories: procedures and functions. A procedures call is a
statement and does not return any value, whereas a function returns a value and must therefore be a part of
an expression.

Subprogram parameters may have three modes.

in
The actual parameter value goes into the call and is not changed there; the formal
parameter is a constant and allows only reading – with a caveat, see Ada
Programming/Constants. This is the default when no mode is given. The actual parameter
can be an expression.
in out
The actual parameter goes into the call and may be redefined. The formal parameter is a
variable and can be read and written.
out
The actual parameter's value before the call is irrelevant, it will get a value in the call. The
formal parameter can be read and written. (In Ada 83 out parameters were write-only.)

A parameter of any mode may also be explicitly aliased.

access
The formal parameter is an access (a pointer) to some variable. (This is not a parameter
mode from the reference manual point of view.)

Note that parameter modes do not specify the parameter passing method. Their purpose is to document the
data flow.
The parameter passing method depends on the type of the parameter. A rule of thumb is that parameters
fitting into a register are passed by copy, others are passed by reference. For certain types, there are special
rules, for others the parameter passing mode is left to the compiler (which you can assume to do what is
most sensible). Tagged types are always passed by reference.

Explicitly aliased parameters and access parameters specify pass by reference.

Unlike in the C class of programming languages, Ada subprogram calls cannot have empty parameters
parentheses ( ) when there are no parameters.

Procedures
A procedure call in Ada constitutes a statement by itself.

For example:

procedure A_Test (A, B: in Integer; C: out Integer) is


begin
C := A + B;
end A_Test;

When the procedure is called with the statement

A_Test (5 + P, 48, Q);

the expressions 5 + P and 48 are evaluated (expressions are only allowed for in parameters), and then
assigned to the formal parameters A and B, which behave like constants. Then, the value A + B is assigned
to formal variable C, whose value will be assigned to the actual parameter Q when the procedure finishes.

C, being an out parameter, is an uninitialized variable before the first assignment. (Therefore in Ada 83,
there existed the restriction that out parameters are write-only. If you wanted to read the value written, you
had to declare a local variable, do all calculations with it, and finally assign it to C before return. This was
awkward and error prone so the restriction was removed in Ada 95.)

Within a procedure, the return statement can be used without arguments to exit the procedure and return the
control to the caller.

For example, to solve an equation of the kind :

with [Link].Elementary_Functions;
use [Link].Elementary_Functions;

procedure Quadratic_Equation
(A, B, C : Float; -- By default it is "in".
R1, R2 : out Float;
Valid : out Boolean)
is
Z : Float;
begin
Z := B**2 - 4.0 * A * C;
if Z < 0.0 or A = 0.0 then
Valid := False; -- Being out parameter, it should be modified at least once.
R1 := 0.0;
R2 := 0.0;
else
Valid := True;
R1 := (-B + Sqrt (Z)) / (2.0 * A);
R2 := (-B - Sqrt (Z)) / (2.0 * A);
end if;
end Quadratic_Equation;

The function SQRT calculates the square root of non-negative values. If the roots are real, they are given
back in R1 and R2, but if they are complex or the equation degenerates (A = 0), the execution of the
procedure finishes after assigning to the Valid variable the False value, so that it is controlled after the call to
the procedure. Notice that the out parameters should be modified at least once, and that if a mode is not
specified, it is implied in.

Functions
A function is a subprogram that can be invoked as part of an expression. Until Ada 2005, functions can
only take in (the default) or access parameters; the latter can be used as a work-around for the
restriction that functions may not have out parameters. Ada 2012 has removed this restriction.

Here is an example of a function body:

function Minimum (A, B: Integer) return Integer is


begin
if A <= B then
return A;
else
return B;
end if;
end Minimum;

(There is, by the way, also the attribute Integer'Min, see RM 3.5.) Or in Ada2012:

function Minimum (A, B: Integer) return Integer is


begin
return (if A <= B then A else B);
end Minimum;

or even shorter as an expression function

function Minimum (A, B: Integer) return Integer is (if A <= B then A else B);

The formal parameters with mode in behave as local constants whose values are provided by the
corresponding actual parameters. The statement return is used to indicate the value returned by the
function call and to give back the control to the expression that called the function. The expression of the
return statement may be of arbitrary complexity and must be of the same type declared in the
specification. If an incompatible type is used, the compiler gives an error. If the restrictions of a subtype are
not fulfilled, e.g. a range, it raises a Constraint_Error exception.

The body of the function can contain several return statements and the execution of any of them will
finish the function, returning control to the caller. If the flow of control within the function branches in
several ways, it is necessary to make sure that each one of them is finished with a return statement. If at
run time the end of a function is reached without encountering a return statement, the exception
Program_Error is raised. Therefore, the body of a function must have at least one such return statement.

Every call to a function produces a new copy of any object declared within it. When the function finalizes,
its objects disappear. Therefore, it is possible to call the function recursively. For example, consider this
implementation of the factorial function:
function Factorial (N : Positive) return Positive is
begin
if N = 1 then
return 1;
else
return (N * Factorial (N - 1));
end if;
end Factorial;

When evaluating the expression Factorial (4); the function will be called with parameter 4 and
within the function it will try to evaluate the expression Factorial (3), calling itself as a function, but
in this case parameter N would be 3 (each call copies the parameters) and so on until N = 1 is evaluated
which will finalize the recursion and then the expression will begin to be completed in the reverse order.

A formal parameter of a function can be of any type, including vectors or records. Nevertheless, it cannot
be an anonymous type, that is, its type must be declared before, for example:

type Float_Vector is array (Positive range <>) of Float;

function Add_Components (V: Float_Vector) return Float is


Result : Float := 0.0;
begin
for I in V'Range loop
Result := Result + V(I);
end loop;
return Result;
end Add_Components;

In this example, the function can be used on a vector of arbitrary dimension. Therefore, there are no static
bounds in the parameters passed to the functions. For example, it is possible to be used in the following
way:

V4 : Float_Vector (1 .. 4) := (1.2, 3.4, 5.6, 7.8);


Sum : Float;

Sum := Add_Components (V4);

In the same way, a function can also return a type whose bounds are not known a priori. For example:

function Invert_Components (V : Float_Vector) return Float_Vector is


Result : Float_Vector(V'Range); -- Fix the bounds of the vector to be returned.
begin
for I in V'Range loop
Result(I) := V (V'First + V'Last - I);
end loop;
return Result;
end Invert_Components;

The variable Result has the same bounds as V, so the returned vector will always have the same dimension
as the one passed as parameter.

A value returned by a function can be used without assigning it to a variable, it can be referenced as an
expression. For example, Invert_Components (V4) (1), where the first element of the vector
returned by the function would be obtained (in this case, the last element of V4, i.e. 7.8).

Named parameters
In subprogram calls, named parameter notation (i.e. the name of the formal parameter followed of the
symbol => and then the actual parameter) allows the rearrangement of the parameters in the call. For
example:

Quadratic_Equation (Valid => OK, A => 1.0, B => 2.0, C => 3.0, R1 => P, R2 => Q);
F := Factorial (N => (3 + I));

This is especially useful to make clear which parameter is which.

Phi := Arctan (A, B);


Phi := Arctan (Y => A, X => B);

The first call (from [Link].Elementary_Functions) is not very clear. One might easily confuse the
parameters. The second call makes the meaning clear without any ambiguity.

Another use is for calls with numeric literals:

Ada.Float_Text_IO.Put_Line (X, 3, 2, 0); -- ?


Ada.Float_Text_IO.Put_Line (X, Fore => 3, Aft => 2, Exp => 0); -- OK

Default parameters
On the other hand, formal parameters may have default values. They can, therefore, be omitted in the
subprogram call. For example:

procedure By_Default_Example (A, B: in Integer := 0);

can be called in these ways:

By_Default_Example (5, 7); -- A = 5, B = 7


By_Default_Example (5); -- A = 5, B = 0
By_Default_Example; -- A = 0, B = 0
By_Default_Example (B => 3); -- A = 0, B = 3
By_Default_Example (1, B => 2); -- A = 1, B = 2

In the first statement, a "regular call" is used (with positional association); the second also uses positional
association but omits the second parameter to use the default; in the third statement, all parameters are by
default; the fourth statement uses named association to omit the first parameter; finally, the fifth statement
uses mixed association, here the positional parameters have to precede the named ones.

Note that the default expression is evaluated once for each formal parameter that has no actual parameter.
Thus, if in the above example a function would be used as defaults for A and B, the function would be
evaluated once in case 2 and 4; twice in case 3, so A and B could have different values; in the others cases,
it would not be evaluated.

Renaming
Subprograms may be renamed. The parameter and result profile for a renaming-as-declaration must be
mode conformant.
procedure Solve
(A, B, C: in Float;
R1, R2 : out Float;
Valid : out Boolean) renames Quadratic_Equation;

This may be especially comfortable for tagged types.

package Some_Package is
type Message_Type is tagged null record;
procedure Print (Message: in Message_Type);
end Some_Package;

with Some_Package;
procedure Main is
Message: Some_Package.Message_Type;
procedure Print renames [Link]; -- this has convention intrinsic, see RM
6.3.1(10.1/2)
Method_Ref: access procedure := Print'Access; -- thus taking 'Access should be illegal;
GNAT GPL 2012 allows this
begin -- All these calls are equivalent:
Some_Package.Print (Message); -- traditional call without use clause
[Link]; -- Ada 2005 [Link] call - note: no use clause
necessary
Print; -- [Link] is a parameterless procedure and can be
renamed as such
Method_Ref.all; -- GNAT GPL 2012 allows illegal call via an access to the
renamed procedure Print
-- This has been corrected in the current version (as of Nov
22, 2012)
end Main;

But note that [Link]'Access; is illegal, you have to use a renaming declaration as above.

Since only mode conformance is required (and not full conformance as between specification and body),
parameter names and default values may be changed with renamings:

procedure P (X: in Integer := 0);


procedure R (A: in Integer := -1) renames P;

See also

Wikibook
Ada Programming
Ada Programming/Operators

Ada 95 Reference Manual


Section 6: Subprograms ([Link] (Annotated (ht
tp://[Link]/standards/95aarm/AARM_HTML/[Link]))
4.4: Expressions ([Link] (Annotated ([Link]
[Link]/standards/95aarm/AARM_HTML/[Link]))

Ada 2005 Reference Manual


Section 6: Subprograms ([Link] (Annotated (htt
p://[Link]/standards/05aarm/html/[Link]))
4.4: Expressions ([Link] (Annotated ([Link]
[Link]/standards/05aarm/html/[Link]))

Ada Quality and Style Guide


4.1.3 Subprograms ([Link]

Retrieved from "[Link]

This page was last edited on 7 November 2022, at 16:40.

Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using
this site, you agree to the Terms of Use and Privacy Policy.

You might also like