# Ada Programming/Subprograms


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.

: 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.\
 : The actual parameter goes into the call and may be redefined. The formal parameter is a variable and can be read and written.\
: 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  parameters were write-only.)

A parameter of any mode may also be explicitly
.

: 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  parameters and
 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:

` A_Test ``A, B: `` Integer; C: `` Integer`` `\
\
`   C := A + B;`\
` 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  parameter, is an uninitialized
variable before the first assignment. (Therefore in Ada 83, there
existed the restriction that  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 $ax^2 + bx + c = 0$:

` ``;`\
`  ``;`\
\
` Quadratic_Equation`\
`   ``A, B, C :     Float;   `\
`    R1, R2  : `` Float;`\
`    Valid   : `` Boolean`\
\
`   Z : Float;`\
\
`   Z := B**2 - 4.0 * A * C;`\
`   `` Z < 0.0 `` A = 0.0 `\
`      Valid := False;  `\
`      R1    := 0.0;`\
`      R2    := 0.0;`\
`   `\
`      Valid := True;`\
`      R1    := (-B + Sqrt (Z)) / (2.0 * A);`\
`      R2    := (-B - Sqrt (Z)) / (2.0 * A);`\
`   `` ``;`\
` 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  parameters should be modified at
least once, and that if a mode is not specified, it is implied
.

## Functions

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

Here is an example of a function body:

` Minimum (A, B: Integer) `` Integer `\
\
`   `` A <= B `\
`      `` A;`\
`   `\
`      `` B;`\
`   `` ``;`\
` Minimum;`

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

` Minimum (A, B: Integer) `` Integer `\
\
`   `` (`` A <= B `` A `` B);`\
` Minimum;`

or even shorter as an *expression function*

` Minimum (A, B: Integer) `` Integer `` (`` A <= B `` A `` B);`

The formal parameters with mode  behave as
local constants whose values are provided by the corresponding actual
parameters. The statement  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  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
 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
 statement. If at run time the end of a
function is reached without encountering a
 statement, the exception Program_Error
is raised. Therefore, the body of a function must have at least one such
 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:

` Factorial (N : Positive) `` Positive `\
\
`   `` N = 1 `\
`      `` 1;`\
`   `\
`      `` (N * Factorial (N - 1));`\
`   `` ``;`\
` 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:

` Float_Vector `` `` (Positive `` <>) `` Float;`\
\
` Add_Components (V: Float_Vector) `` Float `\
`   Result : Float := 0.0;`\
\
`   `` I `` V'`` `\
`      Result := Result + V(I);`\
`   `` ``;`\
`   `` Result;`\
` 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:

` Invert_Components (V : Float_Vector) `` Float_Vector `\
`   Result : Float_Vector(V'``);   `\
\
`   `` I `` V'`` `\
`      Result(I) := V (V'`` + V'`` - I);`\
`   `` ``;`\
`   `` Result;`\
` 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 Ada.Numerics.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:

` By_Default_Example (A, B: `` Integer := 0);`

can be called in these ways:

`By_Default_Example (5, 7);      `\
`By_Default_Example (5);         `\
`By_Default_Example;             `\
`By_Default_Example (B => 3);    `\
`By_Default_Example (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.

` Solve`\
`  (A, B, C: ``  Float;`\
`   R1, R2 : `` Float;`\
`   Valid  : `` Boolean) `` Quadratic_Equation;`

This may be especially comfortable for tagged types.

` Some_Package `\
`  `` Message_Type `` `` `` ``;`\
`  `` Print (Message: `` Message_Type);`\
` Some_Package; `

` Some_Package;`\
` Main `\
`  Message: Some_Package.Message_Type;`\
`  `` Print `` Message.Print;  `\
`  ``<s>`{=html}`Method_Ref: `` `` := Print'``;``</s>`{=html}`  `\
`  `\
`  Some_Package.Print (Message);  `\
`  Message.Print;                 `\
`  Print;                         `\
`  ``<s>`{=html}`Method_Ref.``;``</s>`{=html}`                `\
`                                 `\
` Main;`

But note that `Message.Print'``;` 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:

`P (X: ``Integer :=  0);`\
`R (A: ``Integer := -1) ``P;`

## See also

### Wikibook

-   Ada Programming
-   Ada Programming/Operators

### Ada 95 Reference Manual

-   
-   
### Ada 2005 Reference Manual

-   
-   
### Ada Quality and Style Guide

-   
Programming}}\|Subprograms

es:Programación en
Ada/Subprogramas
