* 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-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
* 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
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