comp.lang.ada
 help / color / mirror / Atom feed
From: Jere <jhb.chat@gmail.com>
Subject: Re: Using Generic Pasckages
Date: Thu, 9 Apr 2020 13:45:50 -0700 (PDT)
Date: 2020-04-09T13:45:50-07:00	[thread overview]
Message-ID: <15129999-1197-4f3c-919b-839fd17e7ee5@googlegroups.com> (raw)
In-Reply-To: <5e8edf69$0$18432$e4fe514c@news.kpn.nl>

On Thursday, April 9, 2020 at 4:40:11 AM UTC-4, ldries46 wrote:
> I have created some generic packages. tese are packages that only do the 
> same thing but with other types. Till now I did only need these packages 
> without interaction with between packages using the same type. I just 
> can declare them:
> Package AA is new BB(type); then calling them as
> A := AA.Get_Value;
> No other declaration seemed to be neccesary .
> 
> Now I have the following situation:
> Package AA is new BB(integer);
> Package CC is new BB(integer);
> and a case where I have several statements using Package AA in one 
> condition and CC the other case.
> I want  to do that by using:
> if D then EE := AA; else EE := CC; end if;
> But I cannot find in the documentation  how the declaration of EE should 
> be made.
> 
> Of course there is the possibility to create the same progrram without 
> using EE but that is far less readable and thus creating more possible 
> errors.
> 
> If I have to do this without the generic packages I already have the 
> program alse will be less readable.

You've already had suggestions for polymorphism or using if/else 
scaffolding.  For run time decisions like this, if both packages
are using the same types, I would recommend polymorphism.  However
if you prefer to stick with generics, you make the scaffolding a bit
less painful by using another generic.  Assuming your generic BB has
a specification like this:

    generic
        type Some_Type is private;
    package BB is
        procedure Set_Value(V : Some_Type);
        function Get_Value return Some_Type;
    end BB;

You can abstract out all your logic using it with another generic
similar to:

    generic
        with package EE is new BB(Some_Type => Integer);
    procedure Do_Stuff;
    
    procedure Do_Stuff is
    
        V : Integer := 23;
    
    begin
        Put_Line(Integer'Image(EE.Get_Value));
        EE.Set_Value(V);
        Put_Line(Integer'Image(EE.Get_Value));
        
        -- All your other BB logic you want to do

    end Do_Stuff;

then you pair it with the if/else or case structure 
and locally declared blocks:

    Put_Line("Hello, world!");
    AA.Set_Value(10);
    CC.Set_Value(20);
  
    if D then 
        declare
            procedure P is new Do_Stuff(AA);
        begin
            P;
        end;
    else
        declare
            procedure P is new Do_Stuff(CC);
        begin
            P;
        end;
    end if;

It still has some scaffolding, but it is more 
readable then tons of if/else blocks scattered
throughout the code.  If your packages don't 
have to rely on Integer, you can change the 
specification to:

    generic
        with package EE is new BB(<>);
    procedure Do_Stuff;

But if your logic actually does rely on knowing
it is an integer type, you will get compiler errors.

Full compilable example below:

with Ada.Text_IO; use Ada.Text_IO;
procedure Hello is
    
    generic
        type Some_Type is private;
    package BB is
        procedure Set_Value(V : Some_Type);
        function Get_Value return Some_Type;
    end BB;
    
    package body BB is
        Value : Some_Type;
        
        procedure Set_Value(V : Some_Type) is
        begin
            Value := V;
        end Set_Value;
        
        function Get_Value return Some_Type is (Value);
    end BB;
    
    package AA is new BB(Integer);
    package CC is new BB(Integer);
    
    generic
        with package EE is new BB(<>);
    procedure Do_Stuff_1;
    
    procedure Do_Stuff_1 is
    
        V : EE.Some_Type := EE.Get_Value;
    
    begin
        EE.Set_Value(V);
    end Do_Stuff_1;
    
    generic
        with package EE is new BB(Some_Type => Integer);
    procedure Do_Stuff_2;
    
    procedure Do_Stuff_2 is
    
        V : Integer := 23;
    
    begin
        Put_Line(Integer'Image(EE.Get_Value));
        EE.Set_Value(V);
        Put_Line(Integer'Image(EE.Get_Value));
    end Do_Stuff_2;
    
    D : Boolean := True;

begin
    Put_Line("Hello, world!");
    AA.Set_Value(10);
    CC.Set_Value(20);
  
    if D then 
        declare
            procedure P is new Do_Stuff_2(AA);
        begin
            P;
        end;
    else
        declare
            procedure P is new Do_Stuff_2(CC);
        begin
            P;
        end;
    end if;
  
end Hello;

  parent reply	other threads:[~2020-04-09 20:45 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-09  8:40 Using Generic Pasckages ldries46
2020-04-09  8:57 ` Dmitry A. Kazakov
2020-04-09 10:05   ` ldries46
2020-04-09 11:23     ` Dmitry A. Kazakov
2020-04-09 15:38 ` AdaMagica
2020-04-09 18:23 ` Simon Wright
2020-04-09 20:45 ` Jere [this message]
2020-04-10 16:34 ` Stephen Leake
2020-04-11 13:16   ` ldries46
2020-04-11 14:15     ` Jeffrey R. Carter
replies disabled

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