comp.lang.ada
 help / color / mirror / Atom feed
From: "Randy Brukardt" <randy@rrsoftware.com>
Subject: Re: Class-wide types algebra
Date: Sat, 1 Oct 2016 00:47:54 -0500
Date: 2016-10-01T00:47:54-05:00	[thread overview]
Message-ID: <nsnilj$cn0$1@franka.jacob-sparre.dk> (raw)
In-Reply-To: nsjrjo$lg8$1@gioia.aioe.org

"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:nsjrjo$lg8$1@gioia.aioe.org...
> On 2016-09-29 20:44, Randy Brukardt wrote:
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:nsii37$fl3$1@gioia.aioe.org...
>>> On 28/09/2016 22:17, Randy Brukardt wrote:
>>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>>> news:nsfrn6$ab7$1@gioia.aioe.org...
>>>>> On 28/09/2016 02:05, Randy Brukardt wrote:
>>>> ...
>>>>>> The problem with all forms of MI is diamond inheritance, which get 
>>>>>> much
>>>>>> worse in Ada because of our strict privacy rules.
>>>>>
>>>>> There is no any problems with diamond inheritance and visibility.
>>>>
>>>> Certainly are. If one has a hidden interface with hidden overridden
>>>> operations, and a later extension tries to add the same interface with
>>>> different overridden operations, one of two things has to happen, both
>>>> bad:
>>>> (1) The interfaces are the same, so the hidden operations completely
>>>> disappear. (The new extension cannot know that they ever existed, so 
>>>> they
>>>> cannot be called from it.) Since the parent operation presumably 
>>>> depends
>>>> on
>>>> those operations, trouble is certain to ensue. (When the operations
>>>> aren't
>>>> overridden, then they magically become visible, which is also a 
>>>> problem.)
>>>> (2) The interfaces are different, so one has problems in dispatching
>>>> calls
>>>> of figuring out which one to call. That way leads to madness.
>>>
>>> It is clearly #2. What you cannot see does not exist, the old good
>>> solipsism. Ada sometimes violates this principle, always for worse.
>>>
>>> There is no problem with dispatching calls so long visibility is
>>> respected:
>>>
>>> 1. Where type's primitive operations are not visible you cannot dispatch
>>> to them.
>>
>> ??? You can always convert an object of the type to the class-wide 
>> interface
>> (which is legal in this scenario, even if not in the private part), and 
>> make
>> a dispatching call. (That's the case that's a problem.).
>
> No, you cannot, you don't see if the type inherits the interface, so you 
> cannot convert to its class.

We're talking about the type that both publically and privately implements 
the same interface. (The private one inherited from the parent, the public 
one directly added.) And we're talking about a conversion that occurs where 
the private interface is visible (so *both* copies of the interface are 
visible). As I said:

>> Which overriding operation do you get?
>
> None, that is illegal, the type does not implement the interface inherited 
> privately. There is no overriding, there is no class in any public scope.

You're not thinking broadly enough about all of the possible combinations of 
public and private inheritance. It just doesn't work. Yes, the "normal" 
cases work, but we have to allow all possibilities (or we're breaking 
privacy).

In particular, when you are in the private scope, you can see both 
interfaces. Whichever one you chose will be wrong about half of the time. 
Such a capability isn't going to help users much, as there will be innumable 
problems caused by it.

...
>> How does it chose which interface to use?
>
> The one visible in this context. There is no unresolved conflicts, in any 
> given context it is unambiguous.

??? Both interfaces are visible in the private context. How could they not 
be both visible  (they're distinct)?


>> ...
>>> Yes, when X were passed as a class-wide of another root type dispatching
>>> to Foo would take the hierarchy of I that this root type uses. It is all
>>> consistent.
>>>
>>>       Y : T1'Class := ...; -- This OK, we see only private I
>>>    begin
>>>       Y.Foo; -- This dispatches on I inherited in P1, WYSIWYG
>>>
>>>    procedure Public is
>>>       X : P2.T2; -- This is OK, we respect privateness
>>>    begin
>>>       X.Foo; -- This dispatches on I inherited in P2
>>
>> Actually, this is madness. Nothing "consistent" about it. Why? Because if
>> you move the call to some outside routine (say some other dispatching
>> operation), the meaning changes. Which means that one can't use
>> abstractions. Very, very bad.
>
> Nothing mad here. You change the type of X that changes the operation. Why 
> X / Y must mean same for Integer X, Y and Float X, Y? How Foo is different 
> from "/"?
>
>>> The important point is that inheritance can be additive as in the case
>>> when I is inherited once privately and once publicly. If succeeds then 
>>> the
>>> outcome is *two* hierarchies.
>>>
>>> You cannot forbid that altogether, which is why you see it as a problem.
>>
>> Well, actually we do: we forbid the private inheritance completely, 
>> because
>> there is no consistent and sensible set of rules for what it would mean.
>
> By violating privacy, by introducing ugly artifacts, by piling up nonsense 
> rules...

There's no violation of privacy. It's illegal to add an interface in a 
private part, but you can of course add the interface visibly. It was the 
best idea that we could come up with, and it had the advantage that if we 
ever could figure out some meaningful semantics that it would be compatible 
to allow private interfaces in the future. The worst possible thing is to 
allow something but get it wrong, because then one have to break all the 
existing usage to fix it (or worse, not fix it).

>>> It is not a problem, just let it be.
>>
>> The implementation of two copies of the same interface would break any of
>> the existing algorithms for implementing interfaces. (I have absolutely 
>> no
>> idea how that could be accomplished; it would depend on how the 
>> dispatching
>> rules were eventually worked out.)
>
> It breaks nothing. You get two hierarchies independent on each other.

Sorry, but you don't have any idea how interface dispatching works. It's 
typically done with some sort of lookup table (since the typical solution of 
ensuring that all of the slots are the same in all of descendants does not 
work when multiple inheritance is allowed). That works because there is only 
one copy of each interface, so there is no need to worry about where they 
come from - one just needs a unique Id where they are declared. If there can 
be multiple copies, that doesn't work. And since these are runtime 
operations,  there doesn't seem to be any way to choose between them --  
runtime knows nothing of visibility.



> You already can do just this with ease:
>
>    generic
>    package P is
>       type I is interface;
>       procedure Foo (X : I) is abstract;
>    end P;
>
>    package P1 is new P;
>    package P2 is new P;
>
>    type T is new P1.I and P2.I with null record;
>    overriding procedure Foo (X : T);

P1.I and P2.I are two different types. In the privacy case, you are getting 
two copies of the same type. Not remotely the same thing. (You can tell the 
difference by trying to call a global class-wide operation that has a 
parameter of the interface. For this example, that won't work for both 
interfaces -- one or the other isn't going to be allowed. For the private 
example, one could call that routine with either interface (because they 
have the same name) -- that's the crux of the problem.

> How is it different from:
>
>    type T is new I and I with null record;

There is only one copy of the interface in this type. It doesn't matter how 
many times you mention it in the declaration or inherit it. But if that was 
applied to private types, it would be what I called case (1), and it would 
badly break privacy.

                             Randy.


  reply	other threads:[~2016-10-01  5:47 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-12 20:26 Class-wide types algebra Dmitry A. Kazakov
2016-09-12 21:12 ` rieachus
2016-09-12 21:39   ` Dmitry A. Kazakov
2016-09-13 11:46     ` rieachus
2016-09-13 12:26       ` Dmitry A. Kazakov
2016-09-28  0:05         ` Randy Brukardt
2016-09-28  7:31           ` Dmitry A. Kazakov
2016-09-28 20:17             ` Randy Brukardt
2016-09-29  8:06               ` Dmitry A. Kazakov
2016-09-29 18:44                 ` Randy Brukardt
2016-09-29 19:55                   ` Dmitry A. Kazakov
2016-10-01  5:47                     ` Randy Brukardt [this message]
2016-10-01  8:35                       ` Dmitry A. Kazakov
2016-10-05 20:42                         ` Randy Brukardt
replies disabled

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