comp.lang.ada
 help / color / mirror / Atom feed
* Generics and Child Packages
@ 2013-08-09 20:35 sbelmont700
  2013-08-10  9:25 ` AdaMagica
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: sbelmont700 @ 2013-08-09 20:35 UTC (permalink / raw)


Does anyone have any tips or tricks when it comes to using child packages and generics?  The whole thing seems pretty kludgy: as soon as you make the parent generic, any public child unit suddenly becomes "faux generic", and has to be instantiated explicitly albeit without any parameters, which at best is a PITA.  More critically, any private child units suddenly becomes forbidden, and you end up with either one gigantic package (bad), or having to split it out and with them in, breaking encapsulation (worse).  Why can't I just instantiate the Parent, and automatically bring along respective copies of all the (parameterless) Children, exactly like it would be if nested packages were used instead of child packages?

-sb


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Generics and Child Packages
  2013-08-09 20:35 Generics and Child Packages sbelmont700
@ 2013-08-10  9:25 ` AdaMagica
  2013-08-10 15:39 ` Felix Krause
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: AdaMagica @ 2013-08-10  9:25 UTC (permalink / raw)


That's a very good question, and I had once the same problem.

The following is a short explanation of the ideas behind private packages:

package P is ... end P;
private package P.Q is ... end P.Q;

A client of P is meant not to be aware of the existence of P.Q. Now if you make P generic, P.Q becomes generic as well.

generic ... package P is ... end P;
private generic package P.Q is ... end P.Q;

So how could a client instantiating P then also instantiate P.Q if he is meant not to be aware of the existence? The only way a private generic package can be used is by instantiating it in a nonprivate child of P or the body of P.

This is the situation.

I see your problem: You have a hierarchy of packages and for some reason you have to make is generic. This is what I tried once - I do not remember how I solved the problem.

I guess a rule saying a private generic child package can only be instantiated as a private child could perhaps solve the problem. But I'm not aware of the full consequences of such a rule.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Generics and Child Packages
  2013-08-09 20:35 Generics and Child Packages sbelmont700
  2013-08-10  9:25 ` AdaMagica
@ 2013-08-10 15:39 ` Felix Krause
  2013-08-11 15:49 ` sbelmont700
  2013-08-12 20:19 ` Randy Brukardt
  3 siblings, 0 replies; 10+ messages in thread
From: Felix Krause @ 2013-08-10 15:39 UTC (permalink / raw)


On 2013-08-09 20:35:31 +0000, sbelmont700@gmail.com said:

> Does anyone have any tips or tricks when it comes to using child 
> packages and generics?  The whole thing seems pretty kludgy: as soon as 
> you make the parent generic, any public child unit suddenly becomes 
> "faux generic", and has to be instantiated explicitly albeit without 
> any parameters, which at best is a PITA.  More critically, any private 
> child units suddenly becomes forbidden, and you end up with either one 
> gigantic package (bad), or having to split it out and with them in, 
> breaking encapsulation (worse).  Why can't I just instantiate the 
> Parent, and automatically bring along respective copies of all the 
> (parameterless) Children, exactly like it would be if nested packages 
> were used instead of child packages?

I have similar problems in my current project. I decided to follow the 
rule that a generic package may never have a child package unless that 
child package takes additional generic arguments. With a bit of work 
and if some preconditions are met, you can transform an existing 
package hierarchy into one that takes generic parameters. Let's have an 
example where we have a package P with some child packages and we want 
to make one base type generic. We start from:

    package P is
       type T_1 is new Integer;
       type T_2 is new Float;
       -- …
    end P;

    private package P.Q is
       -- …
    end P.Q;

    package P.R is
       -- …
    end P.R;

We now want to make the base type of T_2 generic. This is one way how 
this can be done:

    package P is
       -- leave stuff that doesn't depend on the generic parameters here
       type T_1 is new Integer;
    end P;

    generic
       type Base_Type is private;
    package P.Base is
       -- here goes the stuff that was formerly in P and now depends on 
the parameter:
       type T_2 is new Base_Type;
       -- …
    end P.Base;

    private generic
       with package Parent is new P.Base (<>);
    package P.Q is
       -- same as before
    end P.Q;

    generic
       with package Parent is new P.Base (<>);
    package P.R is
       -- same as before
    private
       -- assuming that P.R depends on P.Q
       package My_Q is new P.Q (Parent);
    end P.R;

    generic
       -- same parameters as P.Base:
       type Base_Type is private;
    package P.Whole is
       package Parent ist new P.Base (Base_Type);

       package R is new P.R (Parent);

       -- import declarations from P.Base if you want:
       subtype T_2 is Parent.T_2;
       use type T_2;
    end P.Whole;

You still have a non-generic base package where you can keep 
declarations that do not depend on the generic parameters. P.Whole is a 
convenience package to instantiate all child packages at once, but 
everything is modular - the user does not *need* to use P.Whole. All 
child packages are usable on their own.

However, there are some caveats:

 * You have to instantiate P.Q in every package that needs it. You cannot share
   one instance between packages, because as P.Q as a private child 
unit cannot be
   parameter of the other generic units. This may break your code if 
P.Q defines
   any variables at library level.
 * You cannot access stuff from the private part of P.Base in the other 
packages. All
   private entities you want to share between these packages have to go 
into the
   private part of base package P. If they depend on generic parameters,
   you're out of luck.
 * You cannot have cross-dependencies (like one of the child package's 
implementation
   depends on another package's specification and vice versa).

If you absolutely need to have a child package that does use private 
entities from P.Base, you can of course still define one with empty 
generic parameter set as child unit of P.Base. You could create an 
instance of it in P.Whole for convenience.

-- 
Felix Krause
http://flyx.org/



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Generics and Child Packages
  2013-08-09 20:35 Generics and Child Packages sbelmont700
  2013-08-10  9:25 ` AdaMagica
  2013-08-10 15:39 ` Felix Krause
@ 2013-08-11 15:49 ` sbelmont700
  2013-08-11 16:51   ` Robert A Duff
                     ` (3 more replies)
  2013-08-12 20:19 ` Randy Brukardt
  3 siblings, 4 replies; 10+ messages in thread
From: sbelmont700 @ 2013-08-11 15:49 UTC (permalink / raw)


Thank you both for your response.  I've ended up splitting all packages into separate, unrelated packages that are all generic on all the (common) types, and then having the parent just be instantiations of the others.  This obviously isn't a perfect solution, as the private data is still technically accessible (in that nothing stops a client from instantiating his own version of the private data), and of course it's a whole lot of meaningless typing, but I guess it's the best of a bad situation.

Though I still don't buy the "children of a generic are a generic" explanation.  Semantically there is no difference between a nested package and a child package, so any reason for the latter being "officially" generic (i.e. requiring instantiation) should also apply to the former, which it clearly does not.  It's senseless that this should be okay:

generic
package P
private
   package C is
      ...
   end C;
end P;

but that this should be not:

generic
package P
   ...
end P;

private package P.C is
   ...
end P.C;

when you consider there is no (conceptual) difference.

-sb


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Generics and Child Packages
  2013-08-11 15:49 ` sbelmont700
@ 2013-08-11 16:51   ` Robert A Duff
  2013-08-11 18:30   ` AdaMagica
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Robert A Duff @ 2013-08-11 16:51 UTC (permalink / raw)


sbelmont700@gmail.com writes:

> Though I still don't buy the "children of a generic are a generic"
> explanation.  Semantically there is no difference between a nested
> package and a child package, ...

That ought to be the case, but it's not.  There are lots of
other cases, besides this child-generic thing.  Why is this
legal:

with Ada.Containers.Vectors; use Ada;
package P is
   type T is private;
private
   type T is (Red);
end P;

package P.Q is
   package T_Vectors is new Containers.Vectors
     (Index_Type => Positive, Element_Type => T);
end P.Q;

but this is illegal:

with Ada.Containers.Vectors; use Ada;
package P is
   type T is private;

   package Q is
      package T_Vectors is new Containers.Vectors
        (Index_Type => Positive, Element_Type => T);
   end Q;
private
   type T is (Red);
end P;

For that matter, why should the following be illegal:

package P is
   with Something;
   package Q is
   end Q;
end P;

- Bob

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Generics and Child Packages
  2013-08-11 15:49 ` sbelmont700
  2013-08-11 16:51   ` Robert A Duff
@ 2013-08-11 18:30   ` AdaMagica
  2013-08-11 19:20   ` Shark8
  2013-08-12 20:27   ` Randy Brukardt
  3 siblings, 0 replies; 10+ messages in thread
From: AdaMagica @ 2013-08-11 18:30 UTC (permalink / raw)


On Sunday, August 11, 2013 5:49:06 PM UTC+2, sbelm...@gmail.com wrote:
> Though I still don't buy the "children of a generic are a generic" explanation.  Semantically there is no difference between a nested package and a child package, so any reason for the latter being "officially" generic (i.e. requiring instantiation) should also apply to the former, which it clearly does not.  It's senseless that this should be okay:
> generic
> package P
> private
>    package C is
>       ...
>    end C;
> end P;

With each instantiation, you get a new C.

> but that this should be not:
>
> generic
> package P
>    ...
> end P;
>
> private package P.C is
>    ...
> end P.C;

How should P.C be related to an instantiation of P? P is not a package, only an inst. is a package. Perhaps you could dream up a rule what P.C should be, but it's not obvious.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Generics and Child Packages
  2013-08-11 15:49 ` sbelmont700
  2013-08-11 16:51   ` Robert A Duff
  2013-08-11 18:30   ` AdaMagica
@ 2013-08-11 19:20   ` Shark8
  2013-08-12 20:27   ` Randy Brukardt
  3 siblings, 0 replies; 10+ messages in thread
From: Shark8 @ 2013-08-11 19:20 UTC (permalink / raw)


> Semantically there is no difference between a nested package and a child package, 

Actually there is a bit of a difference: you cannot WITH a nested package like you can a child. Moreover, [WRT the specs,] a child's alteration needn't do anything to what needs recompiled, whereas a nested package does -- therefore the nested package is more tightly bound to its parent than the child is.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Generics and Child Packages
  2013-08-09 20:35 Generics and Child Packages sbelmont700
                   ` (2 preceding siblings ...)
  2013-08-11 15:49 ` sbelmont700
@ 2013-08-12 20:19 ` Randy Brukardt
  3 siblings, 0 replies; 10+ messages in thread
From: Randy Brukardt @ 2013-08-12 20:19 UTC (permalink / raw)


<sbelmont700@gmail.com> wrote in message 
news:d717e583-7238-439e-b60e-c3d0f2177640@googlegroups.com...
>Does anyone have any tips or tricks when it comes to using child packages 
>and generics?

Sure. Don't do it. The rules surrounding those are so complex to implement 
that there is little chance that any compiler has them correct. So you're 
pretty much guarenteeing yourself headaches and non-portable code.

                            Randy.





^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Generics and Child Packages
  2013-08-11 15:49 ` sbelmont700
                     ` (2 preceding siblings ...)
  2013-08-11 19:20   ` Shark8
@ 2013-08-12 20:27   ` Randy Brukardt
  2013-08-12 21:58     ` Simon Wright
  3 siblings, 1 reply; 10+ messages in thread
From: Randy Brukardt @ 2013-08-12 20:27 UTC (permalink / raw)


<sbelmont700@gmail.com> wrote in message 
news:79ec97f1-b5f8-4b12-b351-262fad685f50@googlegroups.com...
...
>Though I still don't buy the "children of a generic are a generic" 
>explanation.

The original rule was "generic units cannot have children". I still think 
that was the better rule. :-)

Very late in the Ada 9x design process, child generics were added with the 
compromise that they would have to require explicit instantiations. 
Otherwise, we'd need to generate implicit instantiations somehow, and that 
would be a very new and complex concept in Ada. Unfortunately, there are a 
lot of problems with the current semantics as well (because withing a child 
of a generic causes an instance of a parent to "sprout" (in the terms of 
Steve Baird) a bunch of additional declarations, and that can cause all 
kinds of wacky conflicts). Those problems would have been multiplied by 10 
if we had allowed implicit instantiations (because of the much larger number 
of implicit declarations).

The whole idea of child units of generics is fatally flawed in my view. It 
just doesn't work semantically.

                                  Randy.




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Generics and Child Packages
  2013-08-12 20:27   ` Randy Brukardt
@ 2013-08-12 21:58     ` Simon Wright
  0 siblings, 0 replies; 10+ messages in thread
From: Simon Wright @ 2013-08-12 21:58 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> The whole idea of child units of generics is fatally flawed in my
> view. It just doesn't work semantically.

Maybe not, but it does _work_ (at least in the Booch Components, in at
least 3 compilers). I do realise that the process needs a lot of
explaining the first few times a user is faced with it, and I'm sure
that the Containers' use of single-instantiation (at least until we come
to synchronised queues ... ok, not the same) is proper.


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2013-08-12 21:58 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-09 20:35 Generics and Child Packages sbelmont700
2013-08-10  9:25 ` AdaMagica
2013-08-10 15:39 ` Felix Krause
2013-08-11 15:49 ` sbelmont700
2013-08-11 16:51   ` Robert A Duff
2013-08-11 18:30   ` AdaMagica
2013-08-11 19:20   ` Shark8
2013-08-12 20:27   ` Randy Brukardt
2013-08-12 21:58     ` Simon Wright
2013-08-12 20:19 ` Randy Brukardt

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