comp.lang.ada
 help / color / mirror / Atom feed
* 2 Ada 95/05 language design questions
@ 2007-02-15 16:21 pnkflyd831
  2007-02-15 18:33 ` Adam Beneschan
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: pnkflyd831 @ 2007-02-15 16:21 UTC (permalink / raw)


I find Ada to be an excellent embedded, real-time, OO language.
However I've noticed over the course of my 3 years programming with
the language 2 ways in which the language behaves that I question the
designers on their rationale.

The first question deals with the decision not to allow the
declaration of abstract subprograms within the private part of a
package (that contains a public abstract tagged type, and uses it as
the controlling operand).  See Ada 05 LRM section 3.9.3(10).  The
Annotated LRM gives a rational (derived tagged types not declared in
child packages would not have visibility to these abstract
subprograms), but wouldn't the better option to be to force derived
tagged type to be declared in the same or child packages than to have
to make public the abstract subprogram?  I do not like the idea of
allowing external objects access to methods that could potentially
leave the aforementioned class objects in an inconsistant state.
(Attempts to impliment the Template Method design pattern suffer from
this issue)


The second question deals with the decision not to have derived tagged
types inherit the "primitive" classwide subprograms of their publicly
declared parents.  See Ada 05 LRM section 3.4(16,17/2, & 23/2) which
states that only primitive operations are inherited and made visible.
In Ada 95 it seems silly to have to with in the package where the
classwide subprogram is declared to use it, and then the package
reference has to be repeated every time the classwide subprogram is
called unless a use clause is present.  The calling object should not
have to distinguish between dispatching and classwide operations when
they have a child derived type view of the object.   In Ada 05, the
impact is less severe because of the dot notation,  but I am still
curious as to why the decision was made. (Code which works with the
child derived type object instead of the parent view of the object
suffer from this issue).




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

* Re: 2 Ada 95/05 language design questions
  2007-02-15 16:21 2 Ada 95/05 language design questions pnkflyd831
@ 2007-02-15 18:33 ` Adam Beneschan
  2007-02-15 18:36 ` Dmitry A. Kazakov
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Adam Beneschan @ 2007-02-15 18:33 UTC (permalink / raw)


On Feb 15, 8:21 am, pnkflyd...@gmail.com wrote:

> The second question deals with the decision not to have derived tagged
> types inherit the "primitive" classwide subprograms of their publicly
> declared parents.  See Ada 05 LRM section 3.4(16,17/2, & 23/2) which
> states that only primitive operations are inherited and made visible.
> In Ada 95 it seems silly to have to with in the package where the
> classwide subprogram is declared to use it, and then the package
> reference has to be repeated every time the classwide subprogram is
> called unless a use clause is present.  The calling object should not
> have to distinguish between dispatching and classwide operations when
> they have a child derived type view of the object.   In Ada 05, the
> impact is less severe because of the dot notation,  but I am still
> curious as to why the decision was made. (Code which works with the
> child derived type object instead of the parent view of the object
> suffer from this issue).

I think your solution could lead to problems.  For one thing, while an
operation can be a dispatching operation of only one tagged type, it
can have several class-wide types in it.  Consider:

   package Pak1 is
       type Root1 is tagged record ... end record;
       type Root2 is tagged record ... end record;
       procedure CW_Operation (X : Root1'Class;
                               Y : Root2'Class);
   end Pak1;

   package Pak2 is
       type Child1 is new Pak1.Root1 with record ... end record;
       type Child2 is new Pak1.Root2 with record ... end record;
       -- (A) inherited subprograms...
   end Pak2;

How many implicit declarations of CW_Operation would there be at (A)?
I count three.  And they'd be overloaded, which means that if you
tried to call CW_Operation on a Child1 and a Child2, all three of them
would be possible meanings for the identifier CW_Operation, and you'd
have to use qualified-type notation on all the parameters to keep the
results from being ambiguous.  (There may be ways to solve this by
adding more rules to the language to say that ambiguous calls are OK
if all the subprograms are just inherited versions of each other, so
that the same code would be called anyway, but this can start to get
very complicated.)

Anyway, the Object.Operation notation of Ada 2005 was put there to
solve this exact problem.  It's unfortunate that the designers missed
this particular problem when designing Ada 95, but it happens---if
they had taken the time to make sure that no flaws were missed, we'd
be calling it Ada 2317 instead of Ada 95.

                      -- Adam






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

* Re: 2 Ada 95/05 language design questions
  2007-02-15 16:21 2 Ada 95/05 language design questions pnkflyd831
  2007-02-15 18:33 ` Adam Beneschan
@ 2007-02-15 18:36 ` Dmitry A. Kazakov
  2007-02-15 20:35 ` Robert A Duff
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Dmitry A. Kazakov @ 2007-02-15 18:36 UTC (permalink / raw)


On 15 Feb 2007 08:21:48 -0800, pnkflyd831@gmail.com wrote:

> I find Ada to be an excellent embedded, real-time, OO language.
> However I've noticed over the course of my 3 years programming with
> the language 2 ways in which the language behaves that I question the
> designers on their rationale.
> 
> The first question deals with the decision not to allow the
> declaration of abstract subprograms within the private part of a
> package (that contains a public abstract tagged type, and uses it as
> the controlling operand).  See Ada 05 LRM section 3.9.3(10).  The
> Annotated LRM gives a rational (derived tagged types not declared in
> child packages would not have visibility to these abstract
> subprograms), but wouldn't the better option to be to force derived
> tagged type to be declared in the same or child packages than to have
> to make public the abstract subprogram?  I do not like the idea of
> allowing external objects access to methods that could potentially
> leave the aforementioned class objects in an inconsistant state.
> (Attempts to impliment the Template Method design pattern suffer from
> this issue)

Yes, this rule is sometimes quite annoying. A similar problem is that
tagged-ness of private types cannot be hidden.

   type S is abstract private; -- Illegal
private   
   type S is abstract tagged null record;

There is nothing wrong in private type extensions.

> The second question deals with the decision not to have derived tagged
> types inherit the "primitive" classwide subprograms of their publicly
> declared parents.  See Ada 05 LRM section 3.4(16,17/2, & 23/2) which
> states that only primitive operations are inherited and made visible.
> In Ada 95 it seems silly to have to with in the package where the
> classwide subprogram is declared to use it, and then the package
> reference has to be repeated every time the classwide subprogram is
> called unless a use clause is present.  The calling object should not
> have to distinguish between dispatching and classwide operations when
> they have a child derived type view of the object.   In Ada 05, the
> impact is less severe because of the dot notation,  but I am still
> curious as to why the decision was made. (Code which works with the
> child derived type object instead of the parent view of the object
> suffer from this issue).

A class-wide subprogram is not primitive. It is defined on T'Class which is
a type distinct from T. Subprograms defined on T'Class are treated
uniformly. Otherwise, it would add an irregularity to the language rules.

As for inherited primitive subprograms their origins don't become any
visible. Consider this:

package P1 is
   type T1 new tagged null record;
   procedure Foo (X : T1);
end P1;

with P1;
package P2 is
   type T2 new P1.T1 with  null record;
end P2;

Now somewhere where P2 is use-d, but P1 is not:

   X : P.T1;
   Y : T2;
begin
   Foo (X); -- Illegal P1.Foo is not directly visible
   Foo (Y); -- Legal P2.Foo is visible, P2.Foo is inherited P1.Foo

You can consider an act of inheritance as a declaration of a *new*
subprogram which body is generated by the compiler:

   procedure Foo (X : T2) is -- This will be visible
   begin
      P1.Foo (P1.T1 (X));
   end  Foo;

P2.Foo is a composition of P1.Foo o P1.T1. Inheritance makes P2.Foo visible
in P2 as any other subprogram declared there. It does not influence P1.Foo.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: 2 Ada 95/05 language design questions
  2007-02-15 16:21 2 Ada 95/05 language design questions pnkflyd831
  2007-02-15 18:33 ` Adam Beneschan
  2007-02-15 18:36 ` Dmitry A. Kazakov
@ 2007-02-15 20:35 ` Robert A Duff
  2007-02-15 22:59   ` pnkflyd831
  2007-02-15 21:51 ` Simon Wright
  2007-02-15 23:00 ` pnkflyd831
  4 siblings, 1 reply; 9+ messages in thread
From: Robert A Duff @ 2007-02-15 20:35 UTC (permalink / raw)


pnkflyd831@gmail.com writes:

> I find Ada to be an excellent embedded, real-time, OO language.
> However I've noticed over the course of my 3 years programming with
> the language 2 ways in which the language behaves that I question the
> designers on their rationale.

Interesting ideas.

> The first question deals with the decision not to allow the
> declaration of abstract subprograms within the private part of a
> package (that contains a public abstract tagged type, and uses it as
> the controlling operand).  See Ada 05 LRM section 3.9.3(10).  The
> Annotated LRM gives a rational (derived tagged types not declared in
> child packages would not have visibility to these abstract
> subprograms), but wouldn't the better option to be to force derived
> tagged type to be declared in the same or child packages than to have
> to make public the abstract subprogram?  I do not like the idea of
> allowing external objects access to methods that could potentially
> leave the aforementioned class objects in an inconsistant state.
> (Attempts to impliment the Template Method design pattern suffer from
> this issue)

That's a legitimate complaint.  However, I think you're suggested cure
is worse than the disease.  You're saying that all (tagged?) type
derivations must happen within the same hierarchy of child packages,
right?  That seems like an onerous restriction, to me.  Quite often, you
want clients, with no visibility on the private part, to derive from the
type and override some operations.

Consider some of the predefined types.  I don't think you want all
controlled types to be declared in children of Ada.Finalization,
nor all types derived from Root_Stream_Type to be declared in children
of Ada.Streams!

One solution would be to have some syntax that means "this type might
have some private abstract operations, and therefore all derivations
from it must be in places where the full type is visible".  But I don't
think you want to treat ALL types that way.

> The second question deals with the decision not to have derived tagged
> types inherit the "primitive" classwide subprograms of their publicly
> declared parents.  See Ada 05 LRM section 3.4(16,17/2, & 23/2) which
> states that only primitive operations are inherited and made visible.
> In Ada 95 it seems silly to have to with in the package where the
> classwide subprogram is declared to use it, and then the package
> reference has to be repeated every time the classwide subprogram is
> called unless a use clause is present.  The calling object should not
> have to distinguish between dispatching and classwide operations when
> they have a child derived type view of the object.   In Ada 05, the
> impact is less severe because of the dot notation,  but I am still
> curious as to why the decision was made. (Code which works with the
> child derived type object instead of the parent view of the object
> suffer from this issue).

Again, a legitimate complaint.  In fact, various people complained about
this over the past decade, and the response was to add the dot-notation
call syntax in Ada 2005.  You say that makes the "impact less severe".
Would you agree with "eliminates the problem"?

As to why it was done that way in the first place, well, I suppose we
didn't think it was that big of a deal.  Sure, you have to track down
the package where the class-wide op is declared, and 'with' that
package, and say "Package_Name.Blah(...)" or else "use Package_Name".
The idea of inheriting class-wide operations never occurred to me;
it just seems weird to me, since there's really only one of it, and you
can't override it.  In a from-scratch language design, I would consider
attacking the problem by liberalizing the visibility rules (e.g. making
with_clauses transitive).

- Bob



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

* Re: 2 Ada 95/05 language design questions
  2007-02-15 16:21 2 Ada 95/05 language design questions pnkflyd831
                   ` (2 preceding siblings ...)
  2007-02-15 20:35 ` Robert A Duff
@ 2007-02-15 21:51 ` Simon Wright
  2007-02-15 23:00 ` pnkflyd831
  4 siblings, 0 replies; 9+ messages in thread
From: Simon Wright @ 2007-02-15 21:51 UTC (permalink / raw)


pnkflyd831@gmail.com writes:

> The first question deals with the decision not to allow the
> declaration of abstract subprograms within the private part of a
> package (that contains a public abstract tagged type, and uses it as
> the controlling operand).

I've used a concrete subprogram that raises Should_Have_Been_Overridden.



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

* Re: 2 Ada 95/05 language design questions
  2007-02-15 20:35 ` Robert A Duff
@ 2007-02-15 22:59   ` pnkflyd831
  2007-02-16  1:51     ` Randy Brukardt
  2007-02-16 18:52     ` Adam Beneschan
  0 siblings, 2 replies; 9+ messages in thread
From: pnkflyd831 @ 2007-02-15 22:59 UTC (permalink / raw)


On Feb 15, 3:35 pm, Robert A Duff <bobd...@shell01.TheWorld.com>
wrote:
> pnkflyd...@gmail.com writes:
> > I find Ada to be an excellent embedded, real-time, OO language.
> > However I've noticed over the course of my 3 years programming with
> > the language 2 ways in which the language behaves that I question the
> > designers on their rationale.
>
> Interesting ideas.
>
> > The first question deals with the decision not to allow the
> > declaration of abstract subprograms within the private part of a
> > package (that contains a public abstract tagged type, and uses it as
> > the controlling operand).  See Ada 05 LRM section 3.9.3(10).  The
> > Annotated LRM gives a rational (derived tagged types not declared in
> > child packages would not have visibility to these abstract
> > subprograms), but wouldn't the better option to be to force derived
> > tagged type to be declared in the same or child packages than to have
> > to make public the abstract subprogram?  I do not like the idea of
> > allowing external objects access to methods that could potentially
> > leave the aforementioned class objects in an inconsistant state.
> > (Attempts to impliment the Template Method design pattern suffer from
> > this issue)
>
> That's a legitimate complaint.  However, I think you're suggested cure
> is worse than the disease.  You're saying that all (tagged?) type
> derivations must happen within the same hierarchy of child packages,
> right?  That seems like an onerous restriction, to me.  Quite often, you
> want clients, with no visibility on the private part, to derive from the
> type and override some operations.
>
> Consider some of the predefined types.  I don't think you want all
> controlled types to be declared in children of Ada.Finalization,
> nor all types derived from Root_Stream_Type to be declared in children
> of Ada.Streams!
>
> One solution would be to have some syntax that means "this type might
> have some private abstract operations, and therefore all derivations
> from it must be in places where the full type is visible".  But I don't
> think you want to treat ALL types that way.
>

Your absolutely correct.  My intent was not that all derived type
linages must match the package lineage.  Additional syntax or the fact
that the private abstract subprogram is still visible from the spec to
the compiler and it could complain at compile time when you attempt to
create a child that doesn't have the full type visible.

>
> Again, a legitimate complaint.  In fact, various people complained about
> this over the past decade, and the response was to add the dot-notation
> call syntax in Ada 2005.  You say that makes the "impact less severe".
> Would you agree with "eliminates the problem"?

You still have to with in the parent tagged types package.  When
refactoring this can still be annoying, but other languages have worse
problems so it's definitely no deal breaker.




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

* Re: 2 Ada 95/05 language design questions
  2007-02-15 16:21 2 Ada 95/05 language design questions pnkflyd831
                   ` (3 preceding siblings ...)
  2007-02-15 21:51 ` Simon Wright
@ 2007-02-15 23:00 ` pnkflyd831
  4 siblings, 0 replies; 9+ messages in thread
From: pnkflyd831 @ 2007-02-15 23:00 UTC (permalink / raw)




Great Points!  Thanks.




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

* RE: 2 Ada 95/05 language design questions
  2007-02-15 22:59   ` pnkflyd831
@ 2007-02-16  1:51     ` Randy Brukardt
  2007-02-16 18:52     ` Adam Beneschan
  1 sibling, 0 replies; 9+ messages in thread
From: Randy Brukardt @ 2007-02-16  1:51 UTC (permalink / raw)
  To: comp.lang.ada

pnkflyd831@gmail.com writes:
> On Feb 15, 3:35 pm, Robert A Duff <bobd...@shell01.TheWorld.com>
> wrote:
...
> > One solution would be to have some syntax that means "this type might
> > have some private abstract operations, and therefore all derivations
> > from it must be in places where the full type is visible".  But I don't
> > think you want to treat ALL types that way.
> >
>
> Your absolutely correct.  My intent was not that all derived type
> linages must match the package lineage.  Additional syntax or the fact
> that the private abstract subprogram is still visible from the spec to
> the compiler and it could complain at compile time when you attempt to
> create a child that doesn't have the full type visible.

Additional syntax is OK. Making the legality of uses (in this case, derived
types) depend on the contents of the private part is not OK. Doing so breaks
encapsulation, in that a supposedly innocent change could cause all kinds of
unrelated code to fail.

I'm mildly surprised that you didn't mention the "no hidden interfaces" rule
of Ada 2007, because that seems to me to be much more problematic than
declaring a hidden abstract operation. OTOH, if you think of interfaces as
properties of a type (either a type has one or it does not; a type cannot
have one more than once), it makes more sense. But I've often thought that
I'm the only one with that particular model...

              Randy.




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

* Re: 2 Ada 95/05 language design questions
  2007-02-15 22:59   ` pnkflyd831
  2007-02-16  1:51     ` Randy Brukardt
@ 2007-02-16 18:52     ` Adam Beneschan
  1 sibling, 0 replies; 9+ messages in thread
From: Adam Beneschan @ 2007-02-16 18:52 UTC (permalink / raw)


On Feb 15, 2:59 pm, pnkflyd...@gmail.com wrote:

> You still have to with in the parent tagged types package.

No, I don't think that's correct.  The following program appears to be
legal, and it compiles with GNAT;  the call to A.CW_Op is legal and
refers to the CW_Op defined in pak1, even though pak1 is not visible
and CW_Op isn't implicitly defined (inherited) in pak2 or pak3:

package pak1 is
    type Root is tagged null record;
    procedure CW_Op (X : in out Root'Class);
end pak1;

with pak1;
package pak2 is
    type Child1 is new pak1.Root with null record;
end pak2;

with pak2;
package pak3 is
    type Child2 is new pak2.Child1 with null record;
end pak3;

with pak3;
procedure test is
    A : pak3.Child2;
begin
    A.CW_Op;
end test;

4.1.3 just says about this notation: "The selector_name (i.e. the
subprogram name) shall resolve to denote a view of a subprogram
declared immediately within the declarative region in which an
ancestor of the type T is declared"; there's nothing in there that
says that the ancestor of T, or the subprogram, has to be visible.

So I think Bob was right about "eliminated".

                       -- Adam




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

end of thread, other threads:[~2007-02-16 18:52 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-15 16:21 2 Ada 95/05 language design questions pnkflyd831
2007-02-15 18:33 ` Adam Beneschan
2007-02-15 18:36 ` Dmitry A. Kazakov
2007-02-15 20:35 ` Robert A Duff
2007-02-15 22:59   ` pnkflyd831
2007-02-16  1:51     ` Randy Brukardt
2007-02-16 18:52     ` Adam Beneschan
2007-02-15 21:51 ` Simon Wright
2007-02-15 23:00 ` pnkflyd831

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