From: Dmitry A. Kazakov on
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
From: Peter C. Chapin on
Markus Schoepflin <nospam(a)no.spam> wrote in
news:he67b2$h79$1(a)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