comp.lang.ada
 help / color / mirror / Atom feed
* Why forbid local generic instantiations?
@ 2019-01-25  9:43 joakimds
  2019-01-25 16:36 ` Jeffrey R. Carter
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: joakimds @ 2019-01-25  9:43 UTC (permalink / raw)


Hi!

Consider the following code:

procedure Main is
   package Integer_Vectors is new Ada.Containers.Vectors (Positive, Integer);
begin
   null;
end Main;

It has a generic package instantiation local to the subprogram Main and not defined on package level. Both in AdaControl and GNATCheck there are rules to forbid local generic instantiations.

For example GNATCheck:
23.7.25 Generics_In_Subprograms

 Flag each declaration of a generic unit in a subprogram. Generic declarations in the bodies of generic subprograms are also flagged. A generic unit nested in another generic unit is not flagged. If a generic unit is declared in a local package that is declared in a subprogram body, the generic unit is flagged. 

This rule has no parameters.




Using AdaControl one can use the following rule to detect insantiations of generic packages/subprograms:
5.10 Declarations

This rule controls usage of various kinds of declarations, possibly only those occurring at specified locations. 
...



Why is it considered bad practise to use local generic instantiations? Within the C++ Community, limiting the use of templates doesn't seem an issue. On the contrary, going all in with template metaprogramming is the norm.

Does local generic instantiations have a performance penalty? Is it something that may be error-prone? Limit cross-compiler compatibility? Why does the rule exist to ban local instantiations? I've been googling/searching the web for an answer to this question but have not found an explanation. Does anybody know?

Best regards,
Joakim


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

* Re: Why forbid local generic instantiations?
  2019-01-25  9:43 Why forbid local generic instantiations? joakimds
@ 2019-01-25 16:36 ` Jeffrey R. Carter
  2019-01-25 21:23   ` Randy Brukardt
  2019-01-25 21:34 ` Randy Brukardt
  2019-01-26 11:11 ` G.B.
  2 siblings, 1 reply; 8+ messages in thread
From: Jeffrey R. Carter @ 2019-01-25 16:36 UTC (permalink / raw)


On 1/25/19 10:43 AM, joakimds@kth.se wrote:
> 
> Why is it considered bad practise to use local generic instantiations? Within the C++ Community, limiting the use of templates doesn't seem an issue. On the contrary, going all in with template metaprogramming is the norm.

It isn't bad practice. Mostly such rules are premature optimization. Are there 
rules against regular pkgs in such places? There's no difference.

It makes perfect sense for things to be declared in the smallest scope in which 
they're needed. This is true of anything, not just pkgs.

A pkg in a subprogram is elaborated every time the subprogram is called. If the 
elaboration of a specific pkg is expensive and timing requirements are tight, it 
might make sense to move that pkg to a larger scope. But a general rule against 
them for "efficiency" doesn't make sense. Limiting it to pkgs that are generic 
instantiations makes less sense.

Perhaps such people don't know that instantiation takes place during compilation 
and has no run-time impact.

As a 1st-order approximation, anything the "C++ Community" does should be avoided.

-- 
Jeff Carter
"I was hobbling along, minding my own business, all of a
sudden, up he comes, cures me! One minute I'm a leper with
a trade, next minute my livelihood's gone! Not so much as a
'by your leave!' You're cured, mate. Bloody do-gooder!"
Monty Python's Life of Brian
76

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

* Re: Why forbid local generic instantiations?
  2019-01-25 16:36 ` Jeffrey R. Carter
@ 2019-01-25 21:23   ` Randy Brukardt
  2019-01-26  9:56     ` Jeffrey R. Carter
  0 siblings, 1 reply; 8+ messages in thread
From: Randy Brukardt @ 2019-01-25 21:23 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:q2fdui$9vn$1@dont-email.me...
...
> Perhaps such people don't know that instantiation takes place during 
> compilation and has no run-time impact.

I agree with most of what you said, but this statement is false, since the 
instance is elaborated at the point of the instantation. Depending on the 
generic, that could be a substantial amount of execution time. (Note that is 
even more true for a code-shared implementation like Janus/Ada, since the 
elaboration of the instance creates the instantiation descriptor.)

                       Randy.



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

* Re: Why forbid local generic instantiations?
  2019-01-25  9:43 Why forbid local generic instantiations? joakimds
  2019-01-25 16:36 ` Jeffrey R. Carter
@ 2019-01-25 21:34 ` Randy Brukardt
  2019-01-26 11:11 ` G.B.
  2 siblings, 0 replies; 8+ messages in thread
From: Randy Brukardt @ 2019-01-25 21:34 UTC (permalink / raw)


<joakimds@kth.se> wrote in message 
news:100ce3ee-71f7-46c7-a24c-dc9c0d280c4f@googlegroups.com...
...
>Why is it considered bad practise to use local generic instantiations? 
>Within the
>C++ Community, limiting the use of templates doesn't seem an issue. On the
>contrary, going all in with template metaprogramming is the norm.

It's not bad practice *in general*, but it might be for particular generics:

(1) In Ada 95, extensions had to be at the same accesibility level as their 
parent, which meant that virtually all generics containing tagged types had 
to be instantiated at library-level. Ada 2005 lifted that restriction, but 
it does have a cost in terms of extra checks and substantially more 
expensive tags. So it could be better to instantiate those generics at 
library-level (even though they can be instantiated locally).

(2) Most compilers (not Janus/Ada or early Rational compilers) make a copy 
of the generic when it is instantiated. Thus, it's usually better to 
instantiate a generic once at library-level and have all of the clients use 
that single instance rather than making multiple copies of the same code. 
(Automatically sharing code is hard for compilers to do.) Even if usage 
would allow a more local instance.

Even compilers like Janus/Ada that use code sharing generate some code at 
the point of the instantiation, so you might want to avoid instantiating the 
same generic multiple times.

(3) Ada requires Legality Rules to be rechecked for an instance, so its 
possible that some generics cannot be instantiated other than at 
library-level (because accessibility checks or various other rules).

Even so, I don't know of any reason to avoid local instances in general. In 
particular, you probably want to instantiate Unchecked_Conversion and 
possibly Unchecked_Deallocation locally. And I'd say that's true about any 
small generic.

In any case, just because some style checker has a rule, that doesn't mean 
it is a good idea to follow it. Lots of people's Ada style guides (not mine, 
of course ;-) have poorly considered rules in them. People who build style 
checkers implement every rule that someone might want, whether or not it is 
good idea is not their concern.

                                       Randy.



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

* Re: Why forbid local generic instantiations?
  2019-01-25 21:23   ` Randy Brukardt
@ 2019-01-26  9:56     ` Jeffrey R. Carter
  2019-01-29  7:35       ` Randy Brukardt
  0 siblings, 1 reply; 8+ messages in thread
From: Jeffrey R. Carter @ 2019-01-26  9:56 UTC (permalink / raw)


On 1/25/19 10:23 PM, Randy Brukardt wrote:
> "Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message
> news:q2fdui$9vn$1@dont-email.me...
> ...
>> Perhaps such people don't know that instantiation takes place during
>> compilation and has no run-time impact.
> 
> I agree with most of what you said, but this statement is false, since the
> instance is elaborated at the point of the instantation. Depending on the
> generic, that could be a substantial amount of execution time. (Note that is
> even more true for a code-shared implementation like Janus/Ada, since the
> elaboration of the instance creates the instantiation descriptor.)

I can't tell from what you've written if what I said is wrong or if we're saying 
basically the same thing in different ways. I'm not familiar with the way 
shared-code generics are instantiated. Macro-expansion instantiation is 
straightforward.

The rule I learned (Ada 83) was: Instantiation happens during compilation; 
elaboration happens during run time.

In more detail: Instantiation is the process whereby a compiler effectively 
replaces an instantiation with a regular pkg (the instance). The result is no 
different from having written the resulting regular pkg instead of the 
instantiation, except for possible code sharing with other instantiations of the 
same generic [ignoring the case of an instantiation in a pkg spec].

All pkgs, regular or generic instances, are elaborated during run time. That 
elaboration can be as complex as the developer wants. In the case of a pkg in a 
subprogram, that elaboration happens every time the subprogram is called.

That's what I learned back when dinosaurs ruled the earth. I gather from what 
you've written that a shared-code compiler may increase the amount of 
elaboration by some (hopefully small, fixed?) amount, so it's not technically 
correct unless the increase is small enough to be considered negligible. I think 
it's correct for compilers that do macro-expansion instantiation, and close 
enough for the rule to be correct as a 1st-order approximation.

If I'm wrong, I'd like to be corrected.

-- 
Jeff Carter
"I feel as though somebody stepped on my tongue
with muddy feet."
Never Give a Sucker an Even Break
112

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

* Re: Why forbid local generic instantiations?
  2019-01-25  9:43 Why forbid local generic instantiations? joakimds
  2019-01-25 16:36 ` Jeffrey R. Carter
  2019-01-25 21:34 ` Randy Brukardt
@ 2019-01-26 11:11 ` G.B.
  2019-01-28 11:43   ` joakimds
  2 siblings, 1 reply; 8+ messages in thread
From: G.B. @ 2019-01-26 11:11 UTC (permalink / raw)


On 25.01.19 10:43, joakimds@kth.se wrote:
> 
> Why is it considered bad practise to use local generic instantiations? Within the C++ Community, limiting the use of templates doesn't seem an issue. On the contrary, going all in with template metaprogramming is the norm.

Note that C++ templates are instantiated at compile time,
whereas Ada generics may be instantiated at runtime. Ada
instances may depend on runtime values.

Locally instantiating a generic may be considered less suitable
if you prefer "flattening" all programs: no hierarchies, no
nesting at all.  Compiler-savvy people may have a preference for
flat, too, I think, if the result is "better" object code.
Or, easier compilation, provided that instantiation at library
level reduces the number of dependencies in scope.
  
Nesting introduces more global entities as a consequence.
There are trade-offs, I think. Spaghetti is the preferred dish
when everything should be "flat": Because if nothing is local,
the connections of objects or instances, such as calls,
need to be explicitly naming all parties,
OTOH, when declarations are directly visible through nesting,
the connections to entities are implicit.

Nesting may offer features connected to local scope, such
as implicit life cycle control; same trade-offs, maybe.

-- 
"HOTDOGS ARE NOT BOOKMARKS"
Springfield Elementary teaching staff

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

* Re: Why forbid local generic instantiations?
  2019-01-26 11:11 ` G.B.
@ 2019-01-28 11:43   ` joakimds
  0 siblings, 0 replies; 8+ messages in thread
From: joakimds @ 2019-01-28 11:43 UTC (permalink / raw)


Thanks for the explainatory replies Jeffrey R. Carter, Randy Brukardt and G.B! Now I understand the issues involved much better.

Best regards,
Joakim


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

* Re: Why forbid local generic instantiations?
  2019-01-26  9:56     ` Jeffrey R. Carter
@ 2019-01-29  7:35       ` Randy Brukardt
  0 siblings, 0 replies; 8+ messages in thread
From: Randy Brukardt @ 2019-01-29  7:35 UTC (permalink / raw)


You're right in saying that there wouldn't be "more code than a usual 
package", but I'd also have complained had you said that "an ordinary 
package body has no run-time impact". In Ada, pretty much everything has a 
run-time impact (at least in the general case, there are specific cases that 
don't).

                             Randy.

"Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:q2hasc$23g$1@dont-email.me...
> On 1/25/19 10:23 PM, Randy Brukardt wrote:
>> "Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message
>> news:q2fdui$9vn$1@dont-email.me...
>> ...
>>> Perhaps such people don't know that instantiation takes place during
>>> compilation and has no run-time impact.
>>
>> I agree with most of what you said, but this statement is false, since 
>> the
>> instance is elaborated at the point of the instantation. Depending on the
>> generic, that could be a substantial amount of execution time. (Note that 
>> is
>> even more true for a code-shared implementation like Janus/Ada, since the
>> elaboration of the instance creates the instantiation descriptor.)
>
> I can't tell from what you've written if what I said is wrong or if we're 
> saying basically the same thing in different ways. I'm not familiar with 
> the way shared-code generics are instantiated. Macro-expansion 
> instantiation is straightforward.
>
> The rule I learned (Ada 83) was: Instantiation happens during compilation; 
> elaboration happens during run time.
>
> In more detail: Instantiation is the process whereby a compiler 
> effectively replaces an instantiation with a regular pkg (the instance). 
> The result is no different from having written the resulting regular pkg 
> instead of the instantiation, except for possible code sharing with other 
> instantiations of the same generic [ignoring the case of an instantiation 
> in a pkg spec].
>
> All pkgs, regular or generic instances, are elaborated during run time. 
> That elaboration can be as complex as the developer wants. In the case of 
> a pkg in a subprogram, that elaboration happens every time the subprogram 
> is called.
>
> That's what I learned back when dinosaurs ruled the earth. I gather from 
> what you've written that a shared-code compiler may increase the amount of 
> elaboration by some (hopefully small, fixed?) amount, so it's not 
> technically correct unless the increase is small enough to be considered 
> negligible. I think it's correct for compilers that do macro-expansion 
> instantiation, and close enough for the rule to be correct as a 1st-order 
> approximation.
>
> If I'm wrong, I'd like to be corrected.
>
> -- 
> Jeff Carter
> "I feel as though somebody stepped on my tongue
> with muddy feet."
> Never Give a Sucker an Even Break
> 112 



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

end of thread, other threads:[~2019-01-29  7:35 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-25  9:43 Why forbid local generic instantiations? joakimds
2019-01-25 16:36 ` Jeffrey R. Carter
2019-01-25 21:23   ` Randy Brukardt
2019-01-26  9:56     ` Jeffrey R. Carter
2019-01-29  7:35       ` Randy Brukardt
2019-01-25 21:34 ` Randy Brukardt
2019-01-26 11:11 ` G.B.
2019-01-28 11:43   ` joakimds

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