comp.lang.ada
 help / color / mirror / Atom feed
* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 13:15 What makes a procedure call 'dispatching' in Ada? Markus Schoepflin
@ 2009-11-20  9:31 ` stefan-lucks
  2009-11-20 14:10   ` Niklas Holsti
  2009-11-20 13:27 ` Dmitry A. Kazakov
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 18+ messages in thread
From: stefan-lucks @ 2009-11-20  9:31 UTC (permalink / raw)


If Foo is a tagged type, then 
   "procedure A(This: [in] [out] Foo)" 

expects *exactly* the same type as the actual parameter. If you want 
"either type Foo or any of its object-oriented children" you write

  "procedure B(This: [in] [out] Foo'Class)".

In your case, Foo is an abstract tagged type. As much as I seem to 
understand Ada, there is no way to actually call procedure A -- because 
you can't have any actuals of an abstract type. (Hey you guys out there, 
am I wrong?)

If I am right, it is very regrettable that the compiler doesn't issue a 
warning when compiling "procedure A(This: [in] [out] Foo)" for an abstract 
type Foo ... perhaps better, a revised Ada should prohibit that. 

So long

Stefan


On Fri, 20 Nov 2009, Markus Schoepflin wrote:


> ---%<---
> package FOOS is
> 
>    type FOO is abstract tagged null record;
> 
>    procedure P (THIS : in FOO);

-------> replace by 
     procedure P (THIS : in FOO'Class);

>    procedure A (THIS : in FOO) is abstract;
> 
> end FOOS;
> 
> package body FOOS is
> 
>    procedure P (THIS : in FOO)

-------> replace by 
     procedure P (THIS : in FOO'Class);

>    is
>    begin
>       A (THIS);
>    end;
> 
> end FOOS;
> --->%---
> 
> When trying to compile this, I get:
> 
> foos.adb:6:07: call to abstract function must be dispatching
> gnatmake: "foos.adb" compilation error
> 
> What is the compiler trying to tell me here? And how do I go about calling
> abstract procedures?
> 
> TIA,
> Markus
> 

-- 
------ Stefan Lucks   --  Bauhaus-University Weimar  --   Germany  ------
               Stefan dot Lucks at uni minus weimar dot de
------  I  love  the  taste  of  Cryptanalysis  in  the  morning!  ------




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

* What makes a procedure call 'dispatching' in Ada?
@ 2009-11-20 13:15 Markus Schoepflin
  2009-11-20  9:31 ` stefan-lucks
                   ` (3 more replies)
  0 siblings, 4 replies; 18+ messages in thread
From: Markus Schoepflin @ 2009-11-20 13:15 UTC (permalink / raw)


Hello,

I'm trying to fell may way around object oriented Ada programming, and I 
think I must be missing something absolutely basic. Please consider the 
following package:

---%<---
package FOOS is

    type FOO is abstract tagged null record;

    procedure P (THIS : in FOO);
    procedure A (THIS : in FOO) is abstract;

end FOOS;

package body FOOS is

    procedure P (THIS : in FOO)
    is
    begin
       A (THIS);
    end;

end FOOS;
--->%---

When trying to compile this, I get:

foos.adb:6:07: call to abstract function must be dispatching
gnatmake: "foos.adb" compilation error

What is the compiler trying to tell me here? And how do I go about calling 
abstract procedures?

TIA,
Markus



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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 13:15 What makes a procedure call 'dispatching' in Ada? Markus Schoepflin
  2009-11-20  9:31 ` stefan-lucks
@ 2009-11-20 13:27 ` Dmitry A. Kazakov
  2009-11-20 13:43   ` Markus Schoepflin
  2009-11-20 13:56 ` Niklas Holsti
  2009-11-20 14:54 ` Ludovic Brenta
  3 siblings, 1 reply; 18+ messages in thread
From: Dmitry A. Kazakov @ 2009-11-20 13:27 UTC (permalink / raw)


On Fri, 20 Nov 2009 14:15:33 +0100, Markus Schoepflin wrote:

> I'm trying to fell may way around object oriented Ada programming, and I 
> think I must be missing something absolutely basic.

> Please consider the following package:
> 
> ---%<---
> package FOOS is
> 
>     type FOO is abstract tagged null record;
> 
>     procedure P (THIS : in FOO);
>     procedure A (THIS : in FOO) is abstract;
> 
> end FOOS;
> 
> package body FOOS is
> 
>     procedure P (THIS : in FOO)
>     is
>     begin
>        A (THIS);
>     end;
> 
> end FOOS;
> --->%---
> 
> When trying to compile this, I get:
> 
> foos.adb:6:07: call to abstract function must be dispatching
> gnatmake: "foos.adb" compilation error
> 
> What is the compiler trying to tell me here? And how do I go about calling 
> abstract procedures?

It tells you that the type of THIS is FOO, so you cannot call to A, because
A is not defined on FOO.

If P is to be defined in terms of any type from the class FOO, then P has
to be declared differently (class-wide):

package FOOS is
    type FOO is abstract tagged null record;
    procedure P (THIS : in FOO'Class);
        -- I am SAME for the whole class rooted in FOO
    procedure A (THIS : in FOO) is abstract;
        -- I have an implementation in each instance of the class except
        -- for the abstract ones like FOO.
end FOOS;

package body FOOS is
   procedure P (THIS : in FOO'Class) is
   begin
      A (THIS);
         -- I do not know what kind of FOO is THIS. So I
         -- dispatch to A according to the tag of THIS.
   end P;
end FOOS;

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



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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 13:27 ` Dmitry A. Kazakov
@ 2009-11-20 13:43   ` Markus Schoepflin
  2009-11-20 13:54     ` RasikaSrinivasan@gmail.com
                       ` (3 more replies)
  0 siblings, 4 replies; 18+ messages in thread
From: Markus Schoepflin @ 2009-11-20 13:43 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

[...]

Thanks for you swift and helpful reply.

> If P is to be defined in terms of any type from the class FOO, then P has
> to be declared differently (class-wide):

So If I understand this correctly, if I want dispatching to happen on a 
given type, I always need to use the class type?

Regards,
Markus



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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 13:43   ` Markus Schoepflin
@ 2009-11-20 13:54     ` RasikaSrinivasan@gmail.com
  2009-11-20 13:58     ` Markus Schoepflin
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 18+ messages in thread
From: RasikaSrinivasan@gmail.com @ 2009-11-20 13:54 UTC (permalink / raw)


On Nov 20, 8:43 am, Markus Schoepflin <nos...@no.spam> wrote:
> Dmitry A. Kazakov wrote:
>
> [...]
>
> Thanks for you swift and helpful reply.
>
> > If P is to be defined in terms of any type from the class FOO, then P has
> > to be declared differently (class-wide):
>
> So If I understand this correctly, if I want dispatching to happen on a
> given type, I always need to use the class type?
>
> Regards,
> Markus

I dont know if the following will clarify or muddle but still here it
goes :

In your original case, the procedure P was defined only for FOO for
which there is no A defined.

On the other hand in Dmitry's modification  P is defined for the whole
family rooted in FOO ie FOO'Class. So A becomes dispatching.

I think there is nothing wrong with the declaration of A and nothing
for the compiler to complain about.

HTH. regards, srini



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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 13:15 What makes a procedure call 'dispatching' in Ada? Markus Schoepflin
  2009-11-20  9:31 ` stefan-lucks
  2009-11-20 13:27 ` Dmitry A. Kazakov
@ 2009-11-20 13:56 ` Niklas Holsti
  2009-11-20 14:31   ` Dmitry A. Kazakov
  2009-11-20 14:54 ` Ludovic Brenta
  3 siblings, 1 reply; 18+ messages in thread
From: Niklas Holsti @ 2009-11-20 13:56 UTC (permalink / raw)


Markus Schoepflin wrote:
> Hello,
> 
> I'm trying to fell may way around object oriented Ada programming, and I 
> think I must be missing something absolutely basic. Please consider the 
> following package:
> 
> ---%<---
> package FOOS is
> 
>    type FOO is abstract tagged null record;
> 
>    procedure P (THIS : in FOO);
>    procedure A (THIS : in FOO) is abstract;
> 
> end FOOS;

No problems there (well, Dmitry will have philosophical objections to 
this design :-)

> package body FOOS is
> 
>    procedure P (THIS : in FOO)
>    is
>    begin
>       A (THIS);

At this point, the compiler knows that THIS is a FOO object, or is to be 
seen as a FOO object. But you have said that the procedure A on FOO is 
abstract -- not implemented -- so you cannot call it.

I assume that your intention is to call the procedure A that is 
implemented (overriden) for the actual object THIS, which is of some 
type derived from FOO .. some type in FOO'Class for which you have 
implemented A. To do so, you must ask the compiler to make this call 
dispatching, by converting the parameter to FOO'Class:

         A (FOO'Class (THIS));

This is called a "redispatching" call, because the procedure P may have 
been reached as the result of a dispatching call on P, and now we are 
asking to dispatch again.

One way to understand this is that in Ada by default calls are 
statically bound, not run-time bound (dispatching). Only calls that have 
  parameters of class type are dispatching.

Dmitry has philosophical objections to redispatching, which is why he 
suggests that you should declare P with a class-type parameter THIS in 
the first place, so that A (THIS) will dispatch. Either will work, but 
in Dmitry's approach you cannot override P for derived types, because it 
is then a class-wide operation, not a primitive operation of FOO. In 
both approaches you can override A for derived types (and you must 
override it because it is abstract in FOO).

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



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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 13:43   ` Markus Schoepflin
  2009-11-20 13:54     ` RasikaSrinivasan@gmail.com
@ 2009-11-20 13:58     ` Markus Schoepflin
  2009-11-20 14:19       ` Niklas Holsti
  2009-11-21 14:07       ` Peter C. Chapin
  2009-11-20 14:00     ` Niklas Holsti
  2009-11-20 14:10     ` Dmitry A. Kazakov
  3 siblings, 2 replies; 18+ messages in thread
From: Markus Schoepflin @ 2009-11-20 13:58 UTC (permalink / raw)


Markus Schoepflin wrote:
> Dmitry A. Kazakov wrote:
> 
> [...]
> 
> Thanks for you swift and helpful reply.
> 
>> If P is to be defined in terms of any type from the class FOO, then P has
>> to be declared differently (class-wide):
> 
> So If I understand this correctly, if I want dispatching to happen on a 
> given type, I always need to use the class type?
> 

And one more question, can I have a dispatching procedure that doesn't 
explicitly use the type it dispatches on? In C++, that would read:

class foo
{
   virtual void f() = 0;
};

class bar
{
   void f() {
     // Do something just depending on class type bar,
     // not on an object of the class, so the 'this' pointer
     // actually is never used.
   }
};

Markus



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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 13:43   ` Markus Schoepflin
  2009-11-20 13:54     ` RasikaSrinivasan@gmail.com
  2009-11-20 13:58     ` Markus Schoepflin
@ 2009-11-20 14:00     ` Niklas Holsti
  2009-11-20 14:10     ` Dmitry A. Kazakov
  3 siblings, 0 replies; 18+ messages in thread
From: Niklas Holsti @ 2009-11-20 14:00 UTC (permalink / raw)


Markus Schoepflin wrote:
> Dmitry A. Kazakov wrote:
> 
> [...]
> 
> Thanks for you swift and helpful reply.
> 
>> If P is to be defined in terms of any type from the class FOO, then P has
>> to be declared differently (class-wide):
> 
> So If I understand this correctly, if I want dispatching to happen on a 
> given type, I always need to use the class type?

Yes. You can do that either by Dmitry's method, declaring the parameter 
as FOO'Class, or by converting a FOO parameter to FOO'Class for the 
call. But note that if an operation has no parameters (and no return 
value) of type FOO (or access FOO), only of FOO'Class, it is not a 
primitive operation of FOO and cannot be overridden in derived types.

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



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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 13:43   ` Markus Schoepflin
                       ` (2 preceding siblings ...)
  2009-11-20 14:00     ` Niklas Holsti
@ 2009-11-20 14:10     ` Dmitry A. Kazakov
  3 siblings, 0 replies; 18+ messages in thread
From: Dmitry A. Kazakov @ 2009-11-20 14:10 UTC (permalink / raw)


On Fri, 20 Nov 2009 14:43:45 +0100, Markus Schoepflin wrote:

> So If I understand this correctly, if I want dispatching to happen on a 
> given type, I always need to use the class type?

Exactly.

This helps both the compiler to make the program much more efficient by
eliminating unnecessary dispatch and you indicating the design problems
like this and making it safer in the opposite cases:

Consider the case where one non-abstract operation calls another:

    type FOO is abstract tagged null record;
    procedure P (THIS : in out FOO);
    procedure A (THIS : in out FOO);

...
    procedure P (THIS : in FOO) is
    begin
        ...
        A (THIS);
           -- This is a part of the implementation of P for the type FOO
        ...
    end P;

Here the call to A does not dispatch. In other language like C++ it would.

Now consider a type derived from FOO, that overrides A, but inherits P.
That could break the implementation of P in C++, but not in Ada, where P
will behave exactly as it did before.

When you design P you should decide whether it is a class-wide subprogram
or not. That role of P will define the behavior of calls to A from its
body. Sometimes the compiler can detect that the declared role of P does
not match its implementation, as it was in your case.

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



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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20  9:31 ` stefan-lucks
@ 2009-11-20 14:10   ` Niklas Holsti
  0 siblings, 0 replies; 18+ messages in thread
From: Niklas Holsti @ 2009-11-20 14:10 UTC (permalink / raw)


 > On Fri, 20 Nov 2009, Markus Schoepflin wrote:
 >
 >
 >> ---%<---
 >> package FOOS is
 >>
 >>    type FOO is abstract tagged null record;
 >>
 >>    procedure P (THIS : in FOO);
 >
 > -------> replace by
 >      procedure P (THIS : in FOO'Class);
 >
 >>    procedure A (THIS : in FOO) is abstract;
 >>
 >> end FOOS;
 >>
 >> package body FOOS is
 >>
 >>    procedure P (THIS : in FOO)
 >
 > -------> replace by
 >      procedure P (THIS : in FOO'Class);
 >
 >>    is
 >>    begin
 >>       A (THIS);
 >>    end;
 >>
 >> end FOOS;
 >> --->%---
 >>
 >> When trying to compile this, I get:
 >>
 >> foos.adb:6:07: call to abstract function must be dispatching
 >> gnatmake: "foos.adb" compilation error
 >>
 >> What is the compiler trying to tell me here? And how do I go
 >> about calling abstract procedures?
 >>
 >> TIA,
 >> Markus

stefan-lucks@see-the.signature wrote:
> If Foo is a tagged type, then 
>    "procedure A(This: [in] [out] Foo)" 
> 
> expects *exactly* the same type as the actual parameter. If you want 
> "either type Foo or any of its object-oriented children" you write
> 
>   "procedure B(This: [in] [out] Foo'Class)".
> 
> In your case, Foo is an abstract tagged type. As much as I seem to 
> understand Ada, there is no way to actually call procedure A -- because 
> you can't have any actuals of an abstract type. (Hey you guys out there, 
> am I wrong?)

There is no way to call A on an object of (apparent) type FOO because A 
is declared as abstract for FOO. The compiler very correctly says that 
such a call is impossible.

But you can call the overriding (concrete) implementation of A for the 
actual type of THIS (some non-abstract type derived from FOO) by 
converting to class-wide to force dispatching:

    A (FOO'Class (THIS));

> If I am right, it is very regrettable that the compiler doesn't issue a 
> warning when compiling "procedure A(This: [in] [out] Foo)" for an abstract 
> type Foo ... perhaps better, a revised Ada should prohibit that. 

There is no reason for such a warning because defining A in this way is 
legal and useful, as long as you convert the parameter to FOO'Class when 
you call it. You can consider the name A (of the abstract operation) a 
kind of place-holder for all the concrete implementations of A for 
derived types.

But Dmitry probably thinks that there should be warning of the form "Bad 
design! Naughty!" :-)

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




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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 13:58     ` Markus Schoepflin
@ 2009-11-20 14:19       ` Niklas Holsti
  2009-11-21 14:07       ` Peter C. Chapin
  1 sibling, 0 replies; 18+ messages in thread
From: Niklas Holsti @ 2009-11-20 14:19 UTC (permalink / raw)


Markus Schoepflin wrote:
> Markus Schoepflin wrote:
>> Dmitry A. Kazakov wrote:
>>
>> [...]
>>
>> Thanks for you swift and helpful reply.
>>
>>> If P is to be defined in terms of any type from the class FOO, then P 
>>> has
>>> to be declared differently (class-wide):
>>
>> So If I understand this correctly, if I want dispatching to happen on 
>> a given type, I always need to use the class type?
>>
> 
> And one more question, can I have a dispatching procedure that doesn't 
> explicitly use the type it dispatches on?

No, as there is no implicit "this" parameter in Ada (and no syntactic 
brackets to group all the operations of a type). To make an operation 
overridable (a "primitive operation" in Ada terms) you have to include 
one or more parameters of the type (or of "access" to the type) or it 
must return a value of the type (or "access" to the type). And moreover 
the operation must be declared in the same package declaration as the type.

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



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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 13:56 ` Niklas Holsti
@ 2009-11-20 14:31   ` Dmitry A. Kazakov
  2009-11-20 15:00     ` Niklas Holsti
  0 siblings, 1 reply; 18+ messages in thread
From: Dmitry A. Kazakov @ 2009-11-20 14:31 UTC (permalink / raw)


On Fri, 20 Nov 2009 15:56:50 +0200, Niklas Holsti wrote:

> Dmitry has philosophical objections to redispatching, which is why he 
> suggests that you should declare P with a class-type parameter THIS in 
> the first place, so that A (THIS) will dispatch.

I would not call them philosophical. If you see the code like

if X = 1 then
   ...
   if X = 1 then
      ...
   end if;
   ...
   if X = 1 then
      ...
   end if;
   ...

you start suggesting that there could be something wrong here. Re-dispatch
is not an error it is an indication of a potential design problem. Why
would you need to check twice the same tag? That requires an explanation in
the design document and comments in the code.

A technical issue is that if we had tagged types of value semantics (i.e.
classes rooted in Boolean, Integer etc), then re-dispatch could not work
with them. I.e. from Ada's agnostic point of view on by-value vs.
by-reference, re-dispatch (or speaking more generally, view conversion to
T'Class) is an implementation-specific kludge.

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



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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 13:15 What makes a procedure call 'dispatching' in Ada? Markus Schoepflin
                   ` (2 preceding siblings ...)
  2009-11-20 13:56 ` Niklas Holsti
@ 2009-11-20 14:54 ` Ludovic Brenta
  3 siblings, 0 replies; 18+ messages in thread
From: Ludovic Brenta @ 2009-11-20 14:54 UTC (permalink / raw)


I'd like to follow up on the (correct) replies in this thread so far
with a "dynamic dispatching in Ada for C++ programmers" primer.

In C++:

class C {
   virtual void foo ();
}
C object;
C* pointer = &object;

void p () {
   object.foo (); // static dispatch
   pointer->foo (); // dynamic dispatch
}

In C++, class types are specific and pointer types are class-wide. The
declaration

C* pointer = &object;

is strictly equivalent to

Object : aliased C;
type C_Access is access all C'Class;
Pointer : C_Access := Object'Access;

Ada makes it explicit that Pointer is of a class-wide type, therefore
calls through the pointer dispatch dynamically:

procedure P is
begin
   Foo (Object); -- static dispatch
   Foo (Pointer.all); -- dynamic dispatch
end P;

So far it seems that Ada and C++ are really the same, but wait! Ada
has a syntax to declare access types to a specific type, like so:

type C_Specific_Access is access all C;

Any calls to primitive operations of C through C_Specific_Access will
dispatch statically, not dynamically. There is no way in C++ to
declare such a type. In C++, all pointer types are class-wide; this
applies also to the type of the implicit "this" parameter.

C onversely, C++ has no way to declare a class-wide type that is not a
pointer or reference type. Ada has C'Class for just this purpose. The
consequence is that, in Ada, you do not need any pointers to achieve
dynamic dispatching whereas C++ requires you to use pointers if you
want dynamic dispatching. Consider again:

void p () {
   object.foo (); // static dispatch
   pointer->foo (); // dynamic dispatch
}

There is no way to dispatch dynamically on "object"; you must use
"pointer"; contrast with Ada:

procedure P (Object : C) is
begin
   Foo (Object); -- static dispatch
   Foo (C'Class (Object)); -- safe dynamic dispatch, without pointers!
end P;

The construct C'Class (Object) is called a "view conversion" in Ada;
it entails no run-time cost and no additional object code in this case
(convert "up" the type hierarchy) but it allows the programmer to
choose whether each call should dispatch statically or dynamically.

HTH

--
Ludovic Brenta.



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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 14:31   ` Dmitry A. Kazakov
@ 2009-11-20 15:00     ` Niklas Holsti
  2009-11-20 18:44       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 18+ messages in thread
From: Niklas Holsti @ 2009-11-20 15:00 UTC (permalink / raw)


Dmitry A. Kazakov wrote:
> On Fri, 20 Nov 2009 15:56:50 +0200, Niklas Holsti wrote:
> 
>> Dmitry has philosophical objections to redispatching, which is why he 
>> suggests that you should declare P with a class-type parameter THIS in 
>> the first place, so that A (THIS) will dispatch.
> 
> I would not call them philosophical.

Please, Dmitry, suggest a better word; perhaps "methodological"? I don't 
want to disparage your view, I understand (I think) the ideas behind it, 
although I don't value them in the same way you do.

> If you see the code like
> 
> if X = 1 then
>    ...
>    if X = 1 then
>       ...
>    end if;
>    ...
>    if X = 1 then
>       ...
>    end if;
>    ...
> 
> you start suggesting that there could be something wrong here.

In the code above, yes, because

    if X = 1 then
       if X = 1 then
          Foo;
       end if;
    end if;

is statically equivalent to the shorter

    if X = 1 then
       Foo;
    end if;

(assuming that X is not volatile, of course).

But the effects of A (THIS) and A (FOO'Class (THIS)) are different, and 
the declaration of an operation as primitive, or class-wide, also has 
significant effects on the design.

A better analogy is code like this:

    procedure John (X : Integer ..) is
    begin
       ...
       if X /= 1 then ...
       end if;
       ...
    end Jonh;

    procedure Mary (...) is
    begin
       if X = 1 then
          John (X);
       else ...
       end if;
    end Mary;

Yes, there is a double check of X, but no, it is not a redundant check.

> Re-dispatch
> is not an error it is an indication of a potential design problem. Why
> would you need to check twice the same tag? That requires an explanation in
> the design document and comments in the code.

I don't want to repeat the (long) discussion we had on this subject, but 
two comments:

- It may be that this is the first check of the tag. The operation that 
contains a (re-)dispatching call may have been called with static 
binding, not dispatching.

- The "explanation" required in the documents and code is simple, and is 
just that redispatching is used to get the most appropriate, specialized 
behaviour of this operation.

> A technical issue is that if we had tagged types of value semantics (i.e.
> classes rooted in Boolean, Integer etc), then re-dispatch could not work
> with them.

Agreed, for pure value semantics. But "object identity" is a central 
idea in object-oriented programming, so pure value semantics is doubtful 
in this area.

 > I.e. from Ada's agnostic point of view on by-value vs.
 > by-reference, re-dispatch (or speaking more generally, view
 > conversion to T'Class) is an implementation-specific kludge.

I think the parameter-passing method (by value or by reference) is not 
the central question; the question is whether we have identifiable 
objects or not. Objects could be passed by value, that is, the bits 
representing the (view of the) object could be copied, but the "value" 
would then have to include some kind of identity label (practically 
speaking, a reference), which would allow redispatching.

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



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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 15:00     ` Niklas Holsti
@ 2009-11-20 18:44       ` Dmitry A. Kazakov
  2009-11-20 20:09         ` Niklas Holsti
  0 siblings, 1 reply; 18+ messages in thread
From: Dmitry A. Kazakov @ 2009-11-20 18:44 UTC (permalink / raw)


On Fri, 20 Nov 2009 17:00:44 +0200, Niklas Holsti wrote:

> A better analogy is code like this:
> 
>     procedure John (X : Integer ..) is
>     begin
>        ...
>        if X /= 1 then ...
>        end if;
>        ...
>     end Jonh;
> 
>     procedure Mary (...) is
>     begin
>        if X = 1 then
>           John (X);
>        else ...
>        end if;
>     end Mary;

This is a wrong analogy. In your example John serves all values of X. So
when you call it with the value 1 it is not like dispatch, which chooses a
body for just one tag. In other words your example is an analogy to calling
a class-wide John from primitive Mary.

> Yes, there is a double check of X, but no, it is not a redundant check.

But with dispatch the check is redundant.

>> A technical issue is that if we had tagged types of value semantics (i.e.
>> classes rooted in Boolean, Integer etc), then re-dispatch could not work
>> with them.
> 
> Agreed, for pure value semantics. But "object identity" is a central 
> idea in object-oriented programming, so pure value semantics is doubtful 
> in this area.

Why is it doubtful? What is wrong with a class rooted in Boolean?

Anyway object identity, if any, is a domain space animal. The way by which
identity is modeled in the program is the programmer's business. You might
believe in the Platonic Universe where each number is unique with an RFID
chip on it, but that does not oblige you to use reference semantics for
integers.

>  > I.e. from Ada's agnostic point of view on by-value vs.
>  > by-reference, re-dispatch (or speaking more generally, view
>  > conversion to T'Class) is an implementation-specific kludge.
> 
> I think the parameter-passing method (by value or by reference) is not 
> the central question; the question is whether we have identifiable 
> objects or not. Objects could be passed by value, that is, the bits 
> representing the (view of the) object could be copied, but the "value" 
> would then have to include some kind of identity label (practically 
> speaking, a reference), which would allow redispatching.

You are conflating "values" of real world objects (modeled) and values of
the language objects (models). There is a mapping between them, but they
are different. Now, what you call identity is just a value (ID), which is
combined with another value (state). There is no mystery in it. You can
copy ID (like you can do the type tag). You can also copy the state (we
ignore here objects bound to hardware ports, random number generators etc).
This is what would happen if you passed a class-wide object by value. No
problem, and no need to re-dispatch, because no dispatch yet occurred. When
you pass only the state, you have to dispatch. Again, no mystery, you do
not lose the identity, it is now the calee's one. This identity in the
callee is statically known, though you might not know which callee among
many. Re-dispatching from a *given* callee is either redundant or worse, a
clash between the callee's identity and one of the actual object in the
caller. Some call it "type error"...

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



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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 18:44       ` Dmitry A. Kazakov
@ 2009-11-20 20:09         ` Niklas Holsti
  2009-11-20 20:59           ` Dmitry A. Kazakov
  0 siblings, 1 reply; 18+ messages in thread
From: Niklas Holsti @ 2009-11-20 20:09 UTC (permalink / raw)


Dmitry A. Kazakov wrote:
> On Fri, 20 Nov 2009 17:00:44 +0200, Niklas Holsti wrote:
> 
>> A better analogy is code like this:
>>
>>     procedure John (X : Integer ..) is
>>     begin
>>        ...
>>        if X /= 1 then ...
>>        end if;
>>        ...
>>     end Jonh;
>>
>>     procedure Mary (...) is
>>     begin
>>        if X = 1 then
>>           John (X);
>>        else ...
>>        end if;
>>     end Mary;
> 
> This is a wrong analogy. In your example John serves all values of X.

You are not seeing the analogy that I intended. John does different 
things for certain values of X, similar to a primitive operation that is 
overridden for certain types (values of X when X is a tag).

> So when you call it with the value 1 it is not like dispatch, which
> chooses a body for just one tag.

The test "if X /= 1" in John is analogous to one dispatch, and the test 
"if X = 1" in Mary to another (perhaps it would have been clearer if the 
latter had been "if X > 2", or some other pair of less correlated 
checks). My point is that it is quite normal and valid to make several 
tests of the same value, as long as the tests are not redundant.

>> Yes, there is a double check of X, but no, it is not a redundant check.
> 
> But with dispatch the check is redundant.

Obviously it is not, because the program behaves quite differently with 
redispatching than without it.

I grant you that for every program that uses redispatching there is an 
equivalent program that does not redispatch and computes the same thing. 
But I, personally, seem to find the redispatching program simpler to 
construct and understand. I also think it is usually shorter, with less 
almost-duplicated code.

I won't comment any more on the "object identity" question -- it becomes 
too philosophical for me (your reference to Plato motivates the use of 
this word :-). Redispatching is a well defined feature of current Ada 
that I find useful and not dangerous -- so far, at least.

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



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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 20:09         ` Niklas Holsti
@ 2009-11-20 20:59           ` Dmitry A. Kazakov
  0 siblings, 0 replies; 18+ messages in thread
From: Dmitry A. Kazakov @ 2009-11-20 20:59 UTC (permalink / raw)


On Fri, 20 Nov 2009 22:09:58 +0200, Niklas Holsti wrote:

> Dmitry A. Kazakov wrote:
>> On Fri, 20 Nov 2009 17:00:44 +0200, Niklas Holsti wrote:
>> 
>>> A better analogy is code like this:
>>>
>>>     procedure John (X : Integer ..) is
>>>     begin
>>>        ...
>>>        if X /= 1 then ...
>>>        end if;
>>>        ...
>>>     end Jonh;
>>>
>>>     procedure Mary (...) is
>>>     begin
>>>        if X = 1 then
>>>           John (X);
>>>        else ...
>>>        end if;
>>>     end Mary;
>> 
>> This is a wrong analogy. In your example John serves all values of X.
> 
> You are not seeing the analogy that I intended. John does different 
> things for certain values of X, similar to a primitive operation that is 
> overridden for certain types (values of X when X is a tag).

A primitive operation as a whole - yes, but a concrete overriding - no. In
Ada these two operations are semantically and also by types different. A
primitive operation is defined on T'Class, an overriding is defined on some
S derived from T.

So if you want an analogy it goes as follows:

integers <---> T'Class
1 <---> S (derived from T)

>> So when you call it with the value 1 it is not like dispatch, which
>> chooses a body for just one tag.
> 
> The test "if X /= 1" in John is analogous to one dispatch,

Actually it does not, because {X | X /=1} is a subset of integers. Dispatch
selects *one* member, not even a singleton subset, just a member.

> and the test 
> "if X = 1" in Mary to another (perhaps it would have been clearer if the 
> latter had been "if X > 2", or some other pair of less correlated 
> checks).

{X | X > 2} also denotes a subset.

> My point is that it is quite normal and valid to make several 
> tests of the same value, as long as the tests are not redundant.

Only, if each of these consequent tests would narrow the primary set of
alternatives, not when these tests just repeating what was already
determined.

Dispatching narrows the set to one element in single step, there is nothing
to narrow afterwards.

BTW, I would favor a model where there would also be possible to narrow to
a subset, e.g. from T'Class to S'Class, or even from (S1..S2)'Class. This
would support consequent sub-dispatches, but still no re-dispatch.

>>> Yes, there is a double check of X, but no, it is not a redundant check.
>> 
>> But with dispatch the check is redundant.
> 
> Obviously it is not, because the program behaves quite differently with 
> redispatching than without it.

We are talking about program semantics. Your argument is like saying that
the loop

   for I in 1..10**6 loop
      declare
         S : String (1..I);
      begin
         null;
      end;
   end loop;

changes the program behavior (it might crash with Storage_Error). Yes it
does, but that behavior change likely is not desired.

Semantically the choice is made, so the behavior shall correspond to the
choice as specified by the type. If the behavior does not correspond it,
that is a bug.

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



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

* Re: What makes a procedure call 'dispatching' in Ada?
  2009-11-20 13:58     ` Markus Schoepflin
  2009-11-20 14:19       ` Niklas Holsti
@ 2009-11-21 14:07       ` Peter C. Chapin
  1 sibling, 0 replies; 18+ messages in thread
From: Peter C. Chapin @ 2009-11-21 14:07 UTC (permalink / raw)


Markus Schoepflin <nospam@no.spam> wrote in
news:he67b2$h79$1@nntp.ilk.net: 

> And one more question, can I have a dispatching procedure that doesn't
> explicitly use the type it dispatches on? In C++, that would read:
> 
> class foo
> {
>    virtual void f() = 0;
> };
> 
> class bar
> {
>    void f() {
>      // Do something just depending on class type bar,
>      // not on an object of the class, so the 'this' pointer
>      // actually is never used.
>    }
> };

The 'this' pointer might never be used, but it is still there anyway. Ada's 
approach to object oriented programming requires that you make 'this' 
explicit. You can, of course, choose to ignore it as well.

Peter




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

end of thread, other threads:[~2009-11-21 14:07 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-20 13:15 What makes a procedure call 'dispatching' in Ada? Markus Schoepflin
2009-11-20  9:31 ` stefan-lucks
2009-11-20 14:10   ` Niklas Holsti
2009-11-20 13:27 ` Dmitry A. Kazakov
2009-11-20 13:43   ` Markus Schoepflin
2009-11-20 13:54     ` RasikaSrinivasan@gmail.com
2009-11-20 13:58     ` Markus Schoepflin
2009-11-20 14:19       ` Niklas Holsti
2009-11-21 14:07       ` Peter C. Chapin
2009-11-20 14:00     ` Niklas Holsti
2009-11-20 14:10     ` Dmitry A. Kazakov
2009-11-20 13:56 ` Niklas Holsti
2009-11-20 14:31   ` Dmitry A. Kazakov
2009-11-20 15:00     ` Niklas Holsti
2009-11-20 18:44       ` Dmitry A. Kazakov
2009-11-20 20:09         ` Niklas Holsti
2009-11-20 20:59           ` Dmitry A. Kazakov
2009-11-20 14:54 ` Ludovic Brenta

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