comp.lang.ada
 help / color / mirror / Atom feed
* Overriding puzzle
@ 2015-12-30 14:49 gautier_niouzes
  2015-12-30 15:10 ` Egil H H
  0 siblings, 1 reply; 12+ messages in thread
From: gautier_niouzes @ 2015-12-30 14:49 UTC (permalink / raw)


Hello,
A small puzzle for year end...
I have a type A and a derived type Custom. How should I redesign things such that a call to New_Page (for an object of type Custom) displays "This is a custom header" and not "This is a normal header", in the code below ? 
TIA for your help!...
_________________________ 
Gautier's Ada programming 
http://sf.net/users/gdemont/

--8<---------8<---------8<---------8<-------

with Ada.Text_IO; use Ada.Text_IO;

procedure Test_override is

  package Pkg is

    type A is tagged null record;
  
    procedure Header(o: A);
    procedure New_Page(o: A);
    
  end;
  
  package body Pkg is
  
    procedure Header(o: A) is
    pragma Unreferenced (o);
    begin
      Put_Line("This is a normal header");
    end;
  
    procedure New_Page(o: A) is
    begin
      Header(o);
    end;
  end;
  
  type Custom is new Pkg.A with null record;

  overriding procedure Header(o: Custom) is
  pragma Unreferenced (o);
  begin
    Put_Line("This is a custom header");
  end;

  obj: Custom;

begin
  obj.New_Page;
end;

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

* Re: Overriding puzzle
  2015-12-30 14:49 Overriding puzzle gautier_niouzes
@ 2015-12-30 15:10 ` Egil H H
  2015-12-30 17:31   ` gautier_niouzes
  2015-12-30 18:07   ` marciant
  0 siblings, 2 replies; 12+ messages in thread
From: Egil H H @ 2015-12-30 15:10 UTC (permalink / raw)


You need to make the call to Header dispatching.
One way would be:

   procedure New_Page(o: A) is 
    begin 
      Header(A'Class(o)); 
    end;

-- 
~egilhh

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

* Re: Overriding puzzle
  2015-12-30 15:10 ` Egil H H
@ 2015-12-30 17:31   ` gautier_niouzes
  2015-12-30 18:07   ` marciant
  1 sibling, 0 replies; 12+ messages in thread
From: gautier_niouzes @ 2015-12-30 17:31 UTC (permalink / raw)


Thanks a lot!
Result visible here - an OSS library: http://sf.net/p/apdf/code/19/
_________________________ 
Gautier's Ada programming 
http://gautiersblog.blogspot.com/search/label/Ada 
NB: follow the above link for a valid e-mail address 


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

* Re: Overriding puzzle
  2015-12-30 15:10 ` Egil H H
  2015-12-30 17:31   ` gautier_niouzes
@ 2015-12-30 18:07   ` marciant
  2015-12-30 18:24     ` gautier_niouzes
  2015-12-30 23:13     ` Randy Brukardt
  1 sibling, 2 replies; 12+ messages in thread
From: marciant @ 2015-12-30 18:07 UTC (permalink / raw)


On Wednesday, December 30, 2015 at 10:10:16 AM UTC-5, Egil H H wrote:
> You need to make the call to Header dispatching.
> One way would be:
> 
>    procedure New_Page(o: A) is 
>     begin 
>       Header(A'Class(o)); 
>     end;
> 
> -- 
> ~egilhh

I do not think that that is it. I think that type custom should be declared in a package like A is.  Even though the New_Page procedure for Custom is overriding the inherited one, it is not a "primitive" operation associated with the type unless it it within the same _package_ as the type.  The Custom type and the overriding procedure are not in a package, they are in a procedure!


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

* Re: Overriding puzzle
  2015-12-30 18:07   ` marciant
@ 2015-12-30 18:24     ` gautier_niouzes
  2015-12-30 21:40       ` marciant
  2015-12-30 23:13     ` Randy Brukardt
  1 sibling, 1 reply; 12+ messages in thread
From: gautier_niouzes @ 2015-12-30 18:24 UTC (permalink / raw)


No, the "A'Class(o)" also makes the difference when type Custom is framed into a package:

with Ada.Text_IO; use Ada.Text_IO;

procedure Test_override is

  package Pkg is
    type A is tagged null record;

    procedure Header(o: A);
    procedure New_Page(o: A);

  end;

  package body Pkg is

    procedure Header(o: A) is
    pragma Unreferenced (o);
    begin
      Put_Line("This is a normal header");
    end;

    procedure New_Page(o: A) is
    begin
      Header(A'Class(o));
    end;
  end;

  package Pkg_cust is
    type Custom is new Pkg.A with null record;
    procedure Header(o: Custom);
  end;

  package body Pkg_cust is
    procedure Header(o: Custom) is
    pragma Unreferenced (o);
    begin
      Put_Line("This is a custom header");
    end;
  end;
    
  use Pkg_cust;
  
  obj: Custom;

begin
  New_Page(obj);
end;

_________________________ 
Gautier's Ada programming 
http://www.openhub.net/accounts/gautier_bd

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

* Re: Overriding puzzle
  2015-12-30 18:24     ` gautier_niouzes
@ 2015-12-30 21:40       ` marciant
  2015-12-30 23:10         ` Randy Brukardt
  0 siblings, 1 reply; 12+ messages in thread
From: marciant @ 2015-12-30 21:40 UTC (permalink / raw)


On Wednesday, December 30, 2015 at 1:24:06 PM UTC-5, gautier...@hotmail.com wrote:
> No, the "A'Class(o)" also makes the difference when type Custom
> is framed into a package:

...

Agil H H was completely right.  I did not read carefully. :(

Sincerely, Vinny

General note to self: tagged type operations that call other operations of the type should always(?) convert the object to its 'class so as to cause dispatching.  Not doing so is probably a defect! 


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

* Re: Overriding puzzle
  2015-12-30 21:40       ` marciant
@ 2015-12-30 23:10         ` Randy Brukardt
  2015-12-31  8:22           ` Niklas Holsti
  2015-12-31 16:30           ` marciant
  0 siblings, 2 replies; 12+ messages in thread
From: Randy Brukardt @ 2015-12-30 23:10 UTC (permalink / raw)


<marciant@earthlink.net> wrote in message 
news:677d0956-63d3-4de8-a6e5-b79c52a1dc12@googlegroups.com...
> On Wednesday, December 30, 2015 at 1:24:06 PM UTC-5, 
> gautier...@hotmail.com wrote:
>> No, the "A'Class(o)" also makes the difference when type Custom
>> is framed into a package:
>
...
> General note to self: tagged type operations that call other operations of 
> the type should always(?) convert the object to its 'class so as to cause 
> dispatching.  Not doing so is probably a defect!

Nooooo. Redispatching is best left for very limited circumstances. There's a 
reason that Ada makes you write it explicitly!

The model of Ada is that within a routine (including inherited routines) the 
object acts as if it had the named type. This makes it much easier to reason 
about the routine, as the behavior of all of the routines called is known.

When you redispatch, you no longer can reason in any useful way about the 
behavior of the call -- essentially you are depending on "magic" (and the 
competency of others) to get the right answer. In limited circumstances 
(like the OP), it works well, but for general programming, look out!

                                             Randy.


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

* Re: Overriding puzzle
  2015-12-30 18:07   ` marciant
  2015-12-30 18:24     ` gautier_niouzes
@ 2015-12-30 23:13     ` Randy Brukardt
  1 sibling, 0 replies; 12+ messages in thread
From: Randy Brukardt @ 2015-12-30 23:13 UTC (permalink / raw)


<marciant@earthlink.net> wrote in message 
news:c63a98f4-1127-4e7d-852f-ad418a4a749f@googlegroups.com...
>I do not think that that is it. I think that type custom should be declared 
>in a package like A is.

In general, you'd be correct, but in the specific instance of a single 
overriding routine, you'll get the right answer in a procedure. But you 
can't add any new primitive operations in a subprogram, and you can't 
override anything after the first body (and most people will only write 
bodies in a subprogram declarative part). Ergo, it works fine for silly 
examples like this one, but it's a bad habit to get into.

                                 Randy.



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

* Re: Overriding puzzle
  2015-12-30 23:10         ` Randy Brukardt
@ 2015-12-31  8:22           ` Niklas Holsti
  2015-12-31  8:42             ` Dmitry A. Kazakov
  2016-01-03  7:18             ` Randy Brukardt
  2015-12-31 16:30           ` marciant
  1 sibling, 2 replies; 12+ messages in thread
From: Niklas Holsti @ 2015-12-31  8:22 UTC (permalink / raw)


On 15-12-31 01:10 , Randy Brukardt wrote:
> <marciant@earthlink.net> wrote in message
> news:677d0956-63d3-4de8-a6e5-b79c52a1dc12@googlegroups.com...
>> On Wednesday, December 30, 2015 at 1:24:06 PM UTC-5,
>> gautier...@hotmail.com wrote:
>>> No, the "A'Class(o)" also makes the difference when type Custom
>>> is framed into a package:
>>
> ...
>> General note to self: tagged type operations that call other operations of
>> the type should always(?) convert the object to its 'class so as to cause
>> dispatching.  Not doing so is probably a defect!
>
> Nooooo. Redispatching is best left for very limited circumstances. There's a
> reason that Ada makes you write it explicitly!

Close to an extreme view, in the spectrum of views... But I agree that 
it is good that Ada requires an explicit indication of redispatching.

> The model of Ada is that within a routine (including inherited routines) the
> object acts as if it had the named type. This makes it much easier to reason
> about the routine, as the behavior of all of the routines called is known.
>
> When you redispatch, you no longer can reason in any useful way about the
> behavior of the call -- essentially you are depending on "magic" (and the
> competency of others) to get the right answer. In limited circumstances
> (like the OP), it works well, but for general programming, look out!

The same (IMO a bit paranoid) argument would logically apply to all 
dispatching calls, including dispatching calls from class-wide subprograms.

The conclusion would be that one cannot reason in any useful way about 
any dispatching call. I don't agree with that conclusion.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .


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

* Re: Overriding puzzle
  2015-12-31  8:22           ` Niklas Holsti
@ 2015-12-31  8:42             ` Dmitry A. Kazakov
  2016-01-03  7:18             ` Randy Brukardt
  1 sibling, 0 replies; 12+ messages in thread
From: Dmitry A. Kazakov @ 2015-12-31  8:42 UTC (permalink / raw)


On 2015-12-31 09:22, Niklas Holsti wrote:
> On 15-12-31 01:10 , Randy Brukardt wrote:

>> The model of Ada is that within a routine (including inherited routines) the
>> object acts as if it had the named type. This makes it much easier to reason
>> about the routine, as the behavior of all of the routines called is
>> known.
>>
>> When you redispatch, you no longer can reason in any useful way about the
>> behavior of the call -- essentially you are depending on "magic" (and the
>> competency of others) to get the right answer. In limited circumstances
>> (like the OP), it works well, but for general programming, look out!
>
> The same (IMO a bit paranoid) argument would logically apply to all
> dispatching calls, including dispatching calls from class-wide subprograms.

A class-wide subprogram is declared class-wide = for all types from the 
class.

> The conclusion would be that one cannot reason in any useful way about
> any dispatching call.

One can. The issue is about the types the reasoning should apply. You 
cannot reason about specific types when you potentially re-dispatch away 
from the specific type stated. But you still can reason about a subclass 
of types even if you dispatch no some of them, unknown in advance.

The point is that IF you are going dispatch THEN, please, state your 
intention in a well-typed way.

Happy New Year!

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


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

* Re: Overriding puzzle
  2015-12-30 23:10         ` Randy Brukardt
  2015-12-31  8:22           ` Niklas Holsti
@ 2015-12-31 16:30           ` marciant
  1 sibling, 0 replies; 12+ messages in thread
From: marciant @ 2015-12-31 16:30 UTC (permalink / raw)


On Wednesday, December 30, 2015 at 6:10:30 PM UTC-5, Randy Brukardt wrote:
> <mar...@earthlink.net> wrote in message 
> news:677...@googlegroups.com...
> > On Wednesday, December 30, 2015 at 1:24:06 PM UTC-5, 
> > gautier...@hotmail.com wrote:
> >> No, the "A'Class(o)" also makes the difference when type Custom
> >> is framed into a package:
> >
> ...
> > General note to self: tagged type operations that call other operations of 
> > the type should always(?) convert the object to its 'class so as to cause 
> > dispatching.  Not doing so is probably a defect!
> 
> Nooooo. Redispatching is best left for very limited circumstances. There's a 
> reason that Ada makes you write it explicitly!

<snipped the reason>

> In limited circumstances 
> (like the OP), it works well, but for general programming, look out!

So, you mean that it would be wrong to try to fall back on the general rule that I stated and that judgement is always necessary in each specific case.
In this case you agree that it goods well.  If the case was such that it would not work well, should the parent type have the "not-to-be-dispatched-to" subprogram be declared as class-wide?  Would you consider it a defect in the implementation of the parent type if such a subprogram was not class-wide?  Shouldn't making a primitive tagged subprogram visible mean that it is thought to be fine to expect that any internal redispatching (that may or may not be caused) would "work well"?   I know - a lot of questions.

But in summary, I'm thinking that you mean that careful case by case design is necessary. 

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

* Re: Overriding puzzle
  2015-12-31  8:22           ` Niklas Holsti
  2015-12-31  8:42             ` Dmitry A. Kazakov
@ 2016-01-03  7:18             ` Randy Brukardt
  1 sibling, 0 replies; 12+ messages in thread
From: Randy Brukardt @ 2016-01-03  7:18 UTC (permalink / raw)


"Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message 
news:dek6taF5o9dU1@mid.individual.net...
> On 15-12-31 01:10 , Randy Brukardt wrote:
...
>> The model of Ada is that within a routine (including inherited routines) 
>> the
>> object acts as if it had the named type. This makes it much easier to 
>> reason
>> about the routine, as the behavior of all of the routines called is 
>> known.
>>
>> When you redispatch, you no longer can reason in any useful way about the
>> behavior of the call -- essentially you are depending on "magic" (and the
>> competency of others) to get the right answer. In limited circumstances
>> (like the OP), it works well, but for general programming, look out!
>
> The same (IMO a bit paranoid) argument would logically apply to all 
> dispatching calls, including dispatching calls from class-wide 
> subprograms.

It does. The problem is that Ada contracts aren't strong enough to describe 
LSP, so clueless (or hasty) programmers can easily write code that violates 
it.

But let me back up a bit. Overloading has a similar problem, but that 
doesn't necessarily mean one has to avoid overloading. Nor do you have to 
avoid dispatching -- it just needs to be used judiciously.

In the specific case of a class-wide subprogram (really a subprogram with 
class-wide parameters), the problem is more obvious (and less dangerous). 
You obviously can't reason about a call based on a specific type, so no one 
will try to do that.

> The conclusion would be that one cannot reason in any useful way about any 
> dispatching call. I don't agree with that conclusion.

Well, you could reason about a call based on LSP, but nothing in Ada forces 
the bodies to follow LSP, so in that case you're just hoping that everyone 
did the right thing. (And since people can extend in the future, you are 
hoping that someone years from now does the right thing -- good luck with 
that.) [Pre'Class helps a bit, but of course there is a lot that can't be 
described that way.]

It's obviously harsh to say that you can't reason about a call, it's more 
that you are making a lot of assumptions in that case that don't necessarily 
hold. So you're on thinner ice that you typically realize.

                          Randy.




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

end of thread, other threads:[~2016-01-03  7:18 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-30 14:49 Overriding puzzle gautier_niouzes
2015-12-30 15:10 ` Egil H H
2015-12-30 17:31   ` gautier_niouzes
2015-12-30 18:07   ` marciant
2015-12-30 18:24     ` gautier_niouzes
2015-12-30 21:40       ` marciant
2015-12-30 23:10         ` Randy Brukardt
2015-12-31  8:22           ` Niklas Holsti
2015-12-31  8:42             ` Dmitry A. Kazakov
2016-01-03  7:18             ` Randy Brukardt
2015-12-31 16:30           ` marciant
2015-12-30 23:13     ` Randy Brukardt

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