Ada: Subprograms
Ada has two kinds of subprograms: procedures (statements that act) and functions (computations that return exactly one value). The split is deliberate — functions are guaranteed side-effect-light, which makes call sites truthful and later enables contracts and proofs.
Procedures and Functions
with Ada.Text_IO; use Ada.Text_IO;
procedure Subprogram_Demo is
-- A procedure: performs an action, returns nothing
procedure Greet (Name : in String) is
begin
Put_Line ("Hello, " & Name & "!");
end Greet;
-- A function: computes and returns exactly one value
function Square (X : in Integer) return Integer is
begin
return X * X;
end Square;
N : constant Integer := 7;
begin
Greet ("Ada"); -- a statement
Put_Line (Integer'Image (Square (N))); -- an expression: 49
end Subprogram_Demo;
Functions cannot be called as statements, and procedures cannot appear in expressions — the compiler enforces the distinction that C's int f() blurs.
Parameter Modes
Every parameter declares a mode: which direction data flows. This is Ada's replacement for guessing what a const T* or T* means:
| Mode | Meaning | Body may… |
|---|---|---|
in (default) | read-only input | read, never assign |
out | result output | assign, initial value uninteresting |
in out | update in place | read and assign |
procedure Modes_Demo is
procedure Swap (A, B : in out Integer) is
Tmp : constant Integer := A;
begin
A := B; -- legal: mode is in out
B := Tmp;
end Swap;
procedure Normalize (X : in out Float; Scale : in Float) is
begin
-- Scale := 1.0; -- compile error: Scale is read-only (in)
X := X / Scale;
end Normalize;
begin
null;
end Modes_Demo;
The compiler checks every mode promise: assigning to an in parameter or reading an out parameter before assigning it are errors. This makes subprogram signatures self-documenting in a way headers in other languages never are.
Overloading
Subprograms may share a name when their parameter profiles differ. The compiler picks by argument types — and ambiguity is an error, not a guess:
procedure Overload_Demo is
function Max (A, B : Integer) return Integer is
(if A > B then A else B); -- expression function: compact body
function Max (A, B : Float) return Float is
(if A > B then A else B);
begin
null; -- Max (3, 5) picks the Integer one; Max (2.0, 9.5) the Float one
end Overload_Demo;
The example also shows an expression function: for a body that is a single expression, is (expression) replaces begin ... return ... end.
Recursion and Declarations
Subprograms can be recursive, and a body can appear before its callers' declarations via is separate or forward declarations in packages — covered in the Packages lesson. A recursive function needs no special keyword:
procedure Recursion_Demo is
function Factorial (N : Natural) return Natural is
(if N <= 1 then 1 else N * Factorial (N - 1));
begin
null; -- Factorial (5) = 120; the type bounds recursion, no tail-call tricks
end Recursion_Demo;
Next: Input/Output.