[comp.lang.ada] factoring with generics

hasan@emx.utexas.edu (David A. Hasan) (03/09/91)

I have a question that deals with using generic subprograms
inside packages as a means of factoring out common implementation
details of the subprograms exported by the package.

Consider a package that exports similar subprograms to its clients:

PACKAGE p IS
   TYPE someType IS ...;
   FUNCTION f1(arg1,arg2 : IN someType) RETURN someType;
   FUNCTION f2(arg1,arg2 : IN someType) RETURN someType;
END p;

and suppose further that the implementations <f1> and <f2> are the same 
except for one subprogram call.  (For example, elementwise addition 
and subtraction of vectors.)

It occurs to me that it might be wise to implement these
as instances of one generic function (<g_f>, say) which takes the 
crucial differing subprogram as a generic parameter.  
To do this, I could:

   1) put the GENERIC DECLARATION and BODY of <g_f> in the body of <p>.
      In this case, the implementations of <f1> & <f2> would 
      instantiate <g_f>.

      But of course, this is hogwash:  generic instantiations
      are *declarations* and cannot be used to define the
      implementation.  So, as an alternative...

   2) put the GENERIC DECLARATION in the package spec and put the
      BODY in the body of package <p>.  <f1> & <f2> could then
      be declared as instances of <g_f>.  This has the pleasant
      side effect of exporting to my clients a generic function
      which they might find useful.

      This works fine until runtime:  when package <p> is elaborated,
      the instantiations for <f1> and <f2> raise PROGRAM_ERROR,
      since the package body (and therefore the body of <g_f>) has 
      not yet been elaborated.

   3) Implement <f1> and <f2> as "skin" routines which simply
      call two internal (to the body of <p>) instances of <g_f>.

      At this point, the simplicity of it all has been lost.


One additional solution might be to factor <g_f> outside of the package
altogether.  However, <f1> and <f2> are fundamentally part of the
abstraction provided by package <p> and cannot be implemented independently.

Is there some way that I have missed to use generics to factor out common
elements of implementations?
--
 :   David A. Hasan
 :   WRW 402 Univ. of Texas at Austin, Austin TX 78712
 :   internet: hasan@emx.cc.utexas.edu 

hasan@ut-emx.uucp (David A. Hasan) (03/12/91)

In article <45358@ut-emx.uucp> I wrote:

>PACKAGE p IS
>   TYPE someType IS ...;
>   FUNCTION f1(arg1,arg2 : IN someType) RETURN someType;
>   FUNCTION f2(arg1,arg2 : IN someType) RETURN someType;
>END p;

[ where <f1> & <f2> differ only in one subprogram call ]

>It occurs to me that it might be wise to implement these
>as instances of one generic function (<g_f>, say) which takes the 
>crucial differing subprogram as a generic parameter.  
>To do this, I could:

>   1) put the GENERIC DECLARATION and BODY of <g_f> in the body of <p>.
>      In this case, the implementations of <f1> & <f2> would 
>      instantiate <g_f>.

>      But of course, this is hogwash:  generic instantiations
>      are *declarations* and cannot be used to define the
>      implementation.  So, as an alternative...

Or *is* it hogwash?  This technique is used by Habermann & Perry
in their book "Ada for Experienced Programmers".  In fact, the
LRM seems to indicate that a generic instantiation can be used
as the implementation of a subprogram.  (I reached this
conclusion by threading my way through the BNF -- a technique
I often use when I can't find an explicit discussion of my
problems.)

The DEC compiler objects to the presence of generic
instantiations such as

   FUNCTION f1 is NEW g_f( ... );

on the basis that it constitutes a redclaration of <f1> as it
appears in the package spec.

Anyone know whether this is legal or not?
-- 
 |   David A. Hasan
 |   hasan@emx.utexas.edu 

loftus@wpllabs.UUCP (William Loftus) (03/14/91)

In article <45441@ut-emx.uucp> hasan@ut-emx.uucp (David A. Hasan) writes:
>In article <45358@ut-emx.uucp> I wrote:
>
>>PACKAGE p IS
>>   TYPE someType IS ...;
>>   FUNCTION f1(arg1,arg2 : IN someType) RETURN someType;
>>   FUNCTION f2(arg1,arg2 : IN someType) RETURN someType;
>>END p;
>
>[ where <f1> & <f2> differ only in one subprogram call ]
>
>>It occurs to me that it might be wise to implement these
>>as instances of one generic function (<g_f>, say) which takes the 
>>crucial differing subprogram as a generic parameter.  
>>To do this, I could:
>
>>   1) put the GENERIC DECLARATION and BODY of <g_f> in the body of <p>.
>>      In this case, the implementations of <f1> & <f2> would 
>>      instantiate <g_f>.
>
>>      But of course, this is hogwash:  generic instantiations
>>      are *declarations* and cannot be used to define the
>>      implementation.  So, as an alternative...
>
>Or *is* it hogwash?  This technique is used by Habermann & Perry
>in their book "Ada for Experienced Programmers".  In fact, the
>LRM seems to indicate that a generic instantiation can be used
>as the implementation of a subprogram.  (I reached this
>conclusion by threading my way through the BNF -- a technique
>I often use when I can't find an explicit discussion of my
>problems.)
>
>The DEC compiler objects to the presence of generic
>instantiations such as
>
>   FUNCTION f1 is NEW g_f( ... );
>
>on the basis that it constitutes a redclaration of <f1> as it
>appears in the package spec.
>
>Anyone know whether this is legal or not?

It is not legal.  A generic instantiation introduces both a spec and body
(see 12.2(1) and 12.2(2)).  A generic instantiation of a procedure in a
package body introduces a spec and body for that routine into the package
body.  If there is a specification of a homograph in the package
specification then there is a redeclaring of the specification of the
subprogram in the package body, and therefore is illegal.  However, this
has been submitted by ALWG as a consideration for Ada 9x.

Also notice that you cannot use a renames solely as an implemenation,
either.
--
William Loftus                   (215) 668 3661
WPL Laboratories, Inc.           UUCP: loftus@wpllabs.UUCP
P.O. Box 111                     ARPA: loftus!wpllabs@prc.unisys.com
216 Wynne Lane
Penn Valley, PA 19072            Ada and Unix Software Consultants

hasan@ut-emx.uucp (David A. Hasan) (03/16/91)

In response to a question I asked about using a generic
subprogram in the body of a package to implement the bodies of
various subprograms exported by that package,

loftus@wpllabs.UUCP (William Loftus) writes:

>A generic instantiation introduces both a spec and body
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                   (I see...)
>(see 12.2(1) and 12.2(2)).  A generic instantiation of a procedure in a
>package body introduces a spec and body for that routine into the package
>body.  If there is a specification of a homograph in the package
>specification then there is a redeclaring of the specification of the
>subprogram in the package body, and therefore is illegal.  However, this
>has been submitted by ALWG as a consideration for Ada 9x.
>

Thank you.  The answers my question exactly.  I must admit,
however, that I still can't see how those two paragraphs of
the LRM tell me this.  Do you perhaps mean 12(1) and 12(2)?
When it says "An instance of a generic subprogram is a
subprogram", is it really telling me that a spec and body are
generated?

My confusion was doubled by the fact that the Meridian
compiler which I also use actually compiled what DEC's
wouldn't (although I did get a runtime PROGRAM_ERROR).

>Also notice that you cannot use a renames solely as an implemenation,
>either.

Yes, I've tried that in the past and had to mend my ways,
also.  Is there a 9X consideration of that?

Anyway, thanks for the help!

-- 
 |   David A. Hasan
 |   hasan@emx.utexas.edu