comp.lang.ada
 help / color / mirror / Atom feed
From: richw@ada-uts.UUCP
Subject: Re: ForTran-Ada + flamette + questi
Date: Mon, 14-Jul-86 13:01:00 EDT	[thread overview]
Date: Mon Jul 14 13:01:00 1986
Message-ID: <4700062@ada-uts> (raw)
In-Reply-To: 8129@cca.UUCP


Sarima (Stanley Friesen) writes:

>>          I fail to see how an enumeration can solve the general
>>  problem (even given your example).  Given that at the time you
>>  write the mapper package you do *not* know what procedures will
>>  be called by it, and that *most* of the procedures to be used do
>>  not even exist yet, *how* can you create an enumeration type
>>  that covers the set?

Your point is valid; I did not explicitly state that modification of
the mapper package is necessary when newly written procedures are to
be passed (I didn't realize this wasn't obvious).  So, in terms of
program maintainance, yes, the mapping method is less convenient; if
you remember, I admitted from the onset that it WAS less convenient.
In any case, thanks for pointing out this ambiguity.

(Note, however, that the pain of having to modify the mapper package
 has nothing to do with WHAT you can do using the method; this mapping
 method STILL provides the same functionality as procedure passing.)

This raises an interesting question: can the mapper package be written
so that when new procedures are to be added, only the body of the
mapper package needs to be recompiled?  This is important when consider-
ing program maintainance because a change to the mapper package's spec
will force recompilation of all users of the mapper (something one would
like to avoid).  The last part of this note outlines a revised spec and
body which avoids having to modify the spec when adding procedures.

>>  The whole point of function pointers as arguments is that it
>>  allows the writing of *generic* procedures which can be
>>  "customized" by the individual user by providing a pointer to a
>>  user supplied routine, this allows the general routine to be
>>  used on data structures or views that were not anticipated when
>>  the original routine was written.

Ah, I'm GLAD you mentioned this.  The use of Ada's generics for such
situations is MUCH more advantageous than passing pointers.  If you
think about it, you can write a much more general "sort" procedure
using generics as opposed to procedure passing because generics lets
you not only vary the procedure used in comparing elements while
sorting -- it also lets you parameterize the TYPE of the elements in
the array you're sorting (assuming you're sorting arrays); can't do
that with procedure passing...


The following is that revised mapper package sketch I promised earlier;
it illustrates how one would pass two types of subprograms: simple
procedures which take no arguments and functions on Strings which return
Integers.

The basic idea involves moving the enumeration type declaration into
the package body.  The 'POS of the enumeration values are passed
around instead of the values themselves.  To make up for the
inability of users to refer to enumeration values by name (since
they no longer appear in the spec), the 'IMAGEs of the enumeration
values are used to create procedure pointers instead.  The costs of
changing the spec in these ways are: (1) More overhead due to the
use of 'VALUE in the body ('POS is not costly -- basically just a
type conversion) and (2) A misspelled procedure name is caught at
runtime (via the UNKNOWN_SUBPROGRAM exception) rather than link
time.

------------------------------------------------------------------------

package Mapper is

    type Procedure_with_0_arguments is private;
    type Function_with_1_in_String_return_Integer is private;

    UNKNOWN_SUBPROGRAM : exception;

    function Create (procedure_name : in String)
        return Procedure_with_0_arguments;
        -- Raises : UNKNOWN_SUBPROGRAM
    function Create (function_name : in String)
        return Function_with_1_in_String_return_Integer;
        -- Raises : UNKNOWN_SUBPROGRAM

    procedure Call (
        p : in Procedure_with_0_arguments);
    function  Call (
        f : in Function_with_1_in_String_return_Integer;
        s : in String)
            return Integer;

    procedure Call (
        procedure_name : in String);
        --
        -- Raises : UNKNOWN_SUBPROGRAM
        --
        -- This is functionally equivalent to:
        --           Call (Create (procedure_name));
        --
    function Call (
        function_name : in String;
        s : in String)
            return Integer;
        --
        -- Raises : UNKNOWN_SUBPROGRAM
        --
        -- This is functionally equivalent to:
        --           Call (Create (function_name), s);

private

    type Procedure_with_0_arguments is new Integer;
    type Function_with_1_in_String_return_Integer is new Integer;

end;

----------------------------------------------------------------------

with proc1;
with proc2;
with func1;
with func2;
     :

package body Mapper is

    type Enums_for_Procedure_with_0_arguments is (
        proc1_enum, proc2_enum, ...);
    type Enums_for_Function_with_1_in_String_return_Integer is (
        func1_enum, func2_enum, ...);
    --
    -- The above will need to be added to when new subprograms are
    -- to be passed.

    function Create (procedure_name : in String)
        return Procedure_with_0_arguments
    is begin
        return Enums_for_Procedure_with_0_arguments'POS (
               Enums_for_Procedure_with_0_arguments'VALUE (
                   procedure_name & "_enum"));
    exception
        when CONSTRAINT_ERROR =>
             raise UNKNOWN_SUBPROGRAM;
    end;

    function Create (function_name : in String)
        return Function_with_1_in_String_return_Integer
    is begin
        return Enums_for_Function_with_1_in_String_return_Integer'POS (
               Enums_for_Function_with_1_in_String_return_Integer'VALUE (
                   function_name & "_enum"));
    exception
        when CONSTRAINT_ERROR =>
             raise UNKNOWN_SUBPROGRAM;
    end;

    -- The following two subprograms will need to be added to when
    -- new subprograms are to be passed.
    --
    procedure Call (p : in Procedure_with_0_arguments)
    is begin
        case Enums_for_Procedure_with_0_arguments'VAL (p) is
            when proc1_enum => proc1;
            when proc2_enum => proc2;
                     :
        end case;
    end;

    function  Call (
        f : in Function_with_1_in_String_return_Integer;
        s : in String)
            return Integer
    is begin
        case Enums_for_Function_with_1_in_String_return_Integer'VAL (f) is
            when func1_enum => return func1 (s);
            when func2_enum => return func2 (s);
                     :
        end case;
    end;

    procedure Call (
        procedure_name : in String)
    is begin
        Call (Create (procedure_name));
    end;

    function Call (
        function_name : in String;
        s : in String)
            return Integer
    is begin
        return Call (Create (function_name), s);
    end;

end;

------------------------------------------------------------------------

Note the "_enum" suffixes for the enumeration literals; I included them
because I'm not sure offhand if there'd be any problem with overloading
the enumeration literals and the subprogram names they represent.

If not, then removing the "_enum" suffix (and removing the call to "&"
in the Create functions) would be a good thing; in any case, you get the
idea...

-- Rich Wagner

  parent reply	other threads:[~1986-07-14 17:01 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1986-05-28 15:54 ForTran-Ada + flamette + question richw
1986-05-30 12:46 ` Russ Holden
1986-06-20 15:36   ` ForTran-Ada + flamette + questi richw
1986-06-22  3:00     ` Russ Holden
1986-06-22  7:49     ` Enumerated "procedural" parameters Alastair Milne
1986-07-03  7:03       ` Dick Dunn
1986-07-10 22:26     ` ForTran-Ada + flamette + questi friesen
1986-07-11 15:38       ` ForTran-Ada ... (really function pointers) markb
1986-07-14 17:01   ` richw [this message]
1986-07-18 21:59     ` ForTran-Ada + flamette + questi vilot
1986-07-22 12:59   ` stt
1986-08-07 13:26     ` Christopher Reedy
  -- strict thread matches above, loose matches on Subject: below --
1986-06-03 19:11 gore
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox