How do I pass a subroutine as a parameter to another subroutine?
-------------------------------------------------------------------------------
Answer 1: (Roger Racine)
-------------------------------------------------------------------------------
With Ada95 it is quite straightforward (see section 3.10
of the Reference Manual). You simply create an access type and use the
access type as the parameter.
-------------------------------------------------------------------------------
with Text_Io; use Text_IO;
procedure Test_Proc_Access is
type Proc_Access_T is access procedure (X : Integer);
procedure My_Proc (X : Integer) is
begin
Put (Integer'Image(X));
end My_Proc;
procedure Call_It (Proc_Access : Proc_Access_T) is
begin
Proc_Access.all(5);
end Call_It;
begin
Call_It (My_Proc'Access);
end Test_Proc_Access;
-------------------------------------------------------------------------------
Answer 2: (Ludovic Brenta)
-------------------------------------------------------------------------------
Generics are usually preferred to access-to-subprograms because they
are safer since no null access value can ever exist.
-------------------------------------------------------------------------------
procedure Test is
generic
with procedure To_Be_Called (The_Parameter : in Whatever);
procedure Generic_Proc;
procedure Generic_Proc is
begin
To_Be_Called (The_Parameter => ...);
end Generic_Proc;
procedure First (The_Parameter : in Whatever) is separate;
procedure Second is new Generic_Proc (To_Be_Called => First);
begin -- Test
Second;
end Test;
-------------------------------------------------------------------------------
Answer 3: (Tom Moran)
-------------------------------------------------------------------------------
Use an abstract tagged type with a subprogram, creating a non-abstract type
with the particular subprogram you want to pass.
-------------------------------------------------------------------------------
-- Here is an example using tagged types to pass a function
-- as a parameter to a procedure. In this example, the passed
-- functions are f(x)=sin(x) and f(x)=a*x+b and the procedure prints
-- the integral from x=0.0 .. 1.0 of the function it is given.
-- tmoran@acm.org 11/11/04 for instructional purposes only
package Integrands is
type Functions is abstract tagged null record;
function F(Selector: Functions;
X : Float) return Float is abstract;
end Integrands;
with Integrands;
package Some_Functions is
type Sin_Type is new Integrands.Functions with null record;
function F(Selector: Sin_Type;
X : Float) return Float;
-- f(x) = sin(x)
type Ramp_Type is new Integrands.Functions with record
A, B : Float;
end record;
function F(Selector: Ramp_Type;
X : Float) return Float;
-- f(x) = a*x+b
end Some_Functions;
with Ada.Numerics.Elementary_Functions;
package body Some_Functions is
function F(Selector: Sin_Type;
X : Float) return Float is
-- f(x) = sin(x)
begin
return Ada.Numerics.Elementary_Functions.Sin(X);
end F;
function F(Selector: Ramp_Type;
X : Float) return Float is
-- f(x) = a*x+b
begin
return Selector.A * X + Selector.B;
end F;
end Some_Functions;
with Ada.Text_Io, Integrands, Some_Functions;
procedure Example is
procedure Integrate(Selector: Integrands.Functions'Class) is
Sum : Float := 0.0;
begin
for I in 1 .. 100 loop
Sum := Sum + 0.01 * Integrands.F(Selector, Float(I) / 100.0);
end loop;
Ada.Text_Io.Put_Line(Float'Image(Sum));
end Integrate;
Do_Sin : Some_Functions.Sin_Type;
Do_Ramp : Some_Functions.Ramp_Type := (A => 1.0, B => 0.0);
begin
Ada.Text_Io.Put("integrated sin=");
Integrate(Do_Sin);
Ada.Text_Io.Put("integrated ramp=");
Integrate(Do_Ramp);
end Example;
-------------------------------------------------------------------------------
|