10. Subroutines

Introduction

------------------------------------------------------------------------------
-- Ada makes a distinction between functions and procedures.
-- Functions always return a value and never alter their parameters.
-- Procedures never return a value and may alter their parameters
procedure Hello is
begin
   Put_Line("hi there!");
end Hello;
-------------------------------
Hello; -- Calling Hello with no parameters
-------------------------------
function Sum(A, B : Integer) return Integer is
begin
   return A + B;
end Sum;
-------------------------------
C := Sum(X, Y); -- Calling a function
------------------------------------------------------------------------------

Accessing Subroutine Arguments

------------------------------------------------------------------------------
-- Ada subroutine parmameters must have one of three modes.
-- IN, OUT, IN OUT
-- IN is read-only inside the subroutine. All function parameters are IN
-- OUT is write-only inside a subroutine
-- IN OUT is read and write within the subroutine
function Hypotenuse(A, B : Float) return Float is
begin
   return sqrt((A**2) + (B**2));
end Hypotenuse;

diag := Hypotenuse(3.0, 4.0); -- diag is 5.0
-------------------------------
Ada.Float_Text_Io.Put(Hypotenuse(3.0, 4.0)); -- prints 5.0E00
------------------------------------------------------------------------------

Making Variables Private to a Function

------------------------------------------------------------------------------
procedure Swap(A, B : in out Integer) is
   Temp := A; -- Temp is visible only within the Swap procedure
begin
   A := B;
   B := Temp;
end Swap;
------------------------------------------------------------------------------

Creating Persistent Private Variables

------------------------------------------------------------------------------
-- Persistent private variables are declared inside a package body
package body Counter is
   type Numbers is mod 100; -- will only have a value from 0 through 99
   Count : Numbers := 0; -- Count is persistent across calls, and is
                         -- initialized to 0
   function Take_Number return Integer is
      Result : Integer := Integer(Count);
   begin
      Count := Count + 1; -- modular arithmetic. 99 + 1 => 0
      return Result;
   end Take_Number;
end Counter;
------------------------------------------------------------------------------

Determining Current Function Name

------------------------------------------------------------------------------
-- Ada provides no way to determine a function's name at run time
------------------------------------------------------------------------------

Passing Arrays and Hashes by Reference

------------------------------------------------------------------------------
-- Ada parameter modes will always pass arrays by reference
-- The GNAT compiler provides a Hash as an extension, but the Ada language
-- does not define a Hash as part of its standard.
------------------------------------------------------------------------------

Detecting Return Context

------------------------------------------------------------------------------
-- Ada return context is always determined at compile time.
-- There is no way to determine return context at run time.
------------------------------------------------------------------------------

Passing by Named Parameter

------------------------------------------------------------------------------
Put(Item => Age, Width => 2);
Put(Item => Age);
Put(Width => 2, Item => Age);
Put(Age, Width => 2);
-------------------------------
function Put(Item : Integer; Width : Positive := 1) is
begin
 [...]
end Put;
------------------------------------------------------------------------------

Skipping Selected Return Values

------------------------------------------------------------------------------
-- Ada functions must return exactly one value. Skipping values does not
-- occur in Ada.
------------------------------------------------------------------------------

Returning More Than One Array or Hash

------------------------------------------------------------------------------
-- Ada allows you to return a single item from a function.
-- That item may be of a compound type, such as an array, an array of arrays,
-- or a record.
------------------------------------------------------------------------------

Returning Failure

------------------------------------------------------------------------------
-- There is no standard Ada failure value. Raise an exception upon failure.
------------------------------------------------------------------------------

Prototyping Functions

------------------------------------------------------------------------------
-- Functions and procedures are prototyped in a package specification
-- The prototype includes the exact signature of the function or procedure
function Take_Number return Integer;
procedure Swap(A, B : in out Integer);
------------------------------------------------------------------------------

Handling Exceptions

------------------------------------------------------------------------------
raise Buffer_Empty_Error; -- raise an exception
-------------------------------
begin
   [...]
exception
   when Buffer_Empty_Exception =>
       [...]
end;
-------------------------------
when Others=>
   Clean_Up;
   raise; -- reraise unknown error
------------------------------------------------------------------------------

Saving Global Values

------------------------------------------------------------------------------
-- Ada global variables are declared within a package specification
package Globals is
   age : Natural;
end Globals;

procedure SetAge(New_Age : Natural) is
begin
   age := New_Age;
end SetAge;
------------------------------------------------------------------------------

Redefining a Function

------------------------------------------------------------------------------
-- Ada does not allow redefinition of functions at run time.
-- Ada does allow functions and procedures to be overloaded.
-- Many functions or procedures can have the same name with a different list
-- of parameters, or a different return type.
type Real_Nums is array(1..100) of Float;
type Int_Nums is array(1..200) of Integer;
function Average(Nums : Real_Nums) return Float;
function Average(Nums : Real_Nums) return Integer;
function Average(Nums : Int_Nums) return Integer;
function Average(Nums : Int_Nums) return Float;
------------------------------------------------------------------------------

Trapping Undefined Function Calls with AUTOLOAD

------------------------------------------------------------------------------
-- Undefined function and procedure calls are detected as errors by the
-- Ada compiler. No run time detection is possible.
------------------------------------------------------------------------------

Nesting Subroutines

------------------------------------------------------------------------------
function Outer(Num : Integer) return Integer is
   function Inner(Arg : Integer) return Integer is
   begin
      return Arg * 19;
   end Inner;
begin -- Outer
   return Num + Inner(Num);
end Outer;
------------------------------------------------------------------------------

Program: Sorting Your Mail

Program: Sorting Your Mail
------------------------------------------------------------------------------
-- To Be Done
------------------------------------------------------------------------------