comp.lang.ada
 help / color / mirror / Atom feed
* Simple example on interfaces
@ 2021-01-25 16:08 Mario Blunk
  2021-01-25 16:41 ` Dmitry A. Kazakov
                   ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: Mario Blunk @ 2021-01-25 16:08 UTC (permalink / raw)


I'm trying to solve a problem of multiple inheritance. It seems to me that an interface could be the solution although the interface is still a mystery for me.

This is the example code:
https://github.com/Blunk-electronic/ada_training/blob/master/src/interfaces_1/interfaces_1.adb

The problem to solve is: 
Type_A2 and type_B1 shall have the property p2 which is type_enum. The anchestors of type_A2 and type_B1 must not have this property. 
Both type_A2 and type_B1 shall inherit p2 from type_C so that p2 must not be written all over again. Would an interface be the solution ?

Thanks for your help.

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

* Re: Simple example on interfaces
  2021-01-25 16:08 Simple example on interfaces Mario Blunk
@ 2021-01-25 16:41 ` Dmitry A. Kazakov
  2021-01-25 17:51   ` Mario Blunk
  2021-01-25 17:00 ` Jeffrey R. Carter
  2021-01-25 19:05 ` Stephen Leake
  2 siblings, 1 reply; 28+ messages in thread
From: Dmitry A. Kazakov @ 2021-01-25 16:41 UTC (permalink / raw)


On 2021-01-25 17:08, Mario Blunk wrote:
> I'm trying to solve a problem of multiple inheritance. It seems to me that an interface could be the solution although the interface is still a mystery for me.
> 
> This is the example code:
> https://github.com/Blunk-electronic/ada_training/blob/master/src/interfaces_1/interfaces_1.adb
> 
> The problem to solve is:
> Type_A2 and type_B1 shall have the property p2 which is type_enum. The anchestors of type_A2 and type_B1 must not have this property.
> Both type_A2 and type_B1 shall inherit p2 from type_C so that p2 must not be written all over again. Would an interface be the solution ?

You must define "property." What is it? In your code these types have p2 
already. Is this static polymorphism not enough? Do you need A2 and B1 
in a class having p2, with polymorphic objects of the class? Then that 
would indeed be an interface.

Now, there is no full multiple inheritance in Ada, if p2 must be a 
component, you are out of luck. You have only one shot and you have 
spent it on p0 in the type Base.

But if p2 could be a function or a getter/setter pair then you can do this:

    type P2_Interface is interface;
    function P2 (Object : P2_Interface) return Enum is abstract;

    type A2 is new A1 and P2_Interface with private;
    overriding function P2 (Object : A2) return Enum;

    type B1 is new Base and P2_Interface with private;
    overriding function P2 (Object : B1) return Enum;

(I removed annoying "type_" prefix from all types)

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

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

* Re: Simple example on interfaces
  2021-01-25 16:08 Simple example on interfaces Mario Blunk
  2021-01-25 16:41 ` Dmitry A. Kazakov
@ 2021-01-25 17:00 ` Jeffrey R. Carter
  2021-01-27  1:48   ` philip...@gmail.com
  2021-01-27  3:36   ` Randy Brukardt
  2021-01-25 19:05 ` Stephen Leake
  2 siblings, 2 replies; 28+ messages in thread
From: Jeffrey R. Carter @ 2021-01-25 17:00 UTC (permalink / raw)


On 1/25/21 5:08 PM, Mario Blunk wrote:
> I'm trying to solve a problem of multiple inheritance. It seems to me that an interface could be the solution although the interface is still a mystery for me.

"IMHO, Interfaces are worthless."
Randy Brukardt

-- 
Jeff Carter
"You cheesy lot of second-hand electric donkey-bottom biters."
Monty Python & the Holy Grail
14

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

* Re: Simple example on interfaces
  2021-01-25 16:41 ` Dmitry A. Kazakov
@ 2021-01-25 17:51   ` Mario Blunk
  2021-01-25 22:06     ` Dmitry A. Kazakov
  2021-01-26 10:02     ` Stephen Leake
  0 siblings, 2 replies; 28+ messages in thread
From: Mario Blunk @ 2021-01-25 17:51 UTC (permalink / raw)



> You must define "property." What is it? 
With "property" I mean the selectors like p0, p1 or p2.
> In your code these types have p2 
> already. Is this static polymorphism not enough? 
It seems so. Suppose there would be more types like C1, D1, ..., each of which derived from type_base, then
I don't want to define p2 over and over.

> Do you need A2 and B1 
> in a class having p2, with polymorphic objects of the class? Then that 
> would indeed be an interface. 
How would that look like ?

> Now, there is no full multiple inheritance in Ada, if p2 must be a 
> component, you are out of luck. You have only one shot and you have 
> spent it on p0 in the type Base. 
That is forbidden as far as the final application is concerned. The example I posted here is a simplification of a more complex scenario.

> But if p2 could be a function or a getter/setter pair then you can do this: 
> 
> type P2_Interface is interface; 
> function P2 (Object : P2_Interface) return Enum is abstract; 
> 
> type A2 is new A1 and P2_Interface with private; 
> overriding function P2 (Object : A2) return Enum; 
> 
> type B1 is new Base and P2_Interface with private; 
> overriding function P2 (Object : B1) return Enum; 
I need to digest that... I know an interface can not have a selector, just abstract functions.
 
> (I removed annoying "type_" prefix from all types) 
I got used to this notation in order to avoid confusion between a type and a variable. Not important here.

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

* Re: Simple example on interfaces
  2021-01-25 16:08 Simple example on interfaces Mario Blunk
  2021-01-25 16:41 ` Dmitry A. Kazakov
  2021-01-25 17:00 ` Jeffrey R. Carter
@ 2021-01-25 19:05 ` Stephen Leake
  2 siblings, 0 replies; 28+ messages in thread
From: Stephen Leake @ 2021-01-25 19:05 UTC (permalink / raw)


Mario Blunk <marioblunk.alere@gmail.com> writes:

> I'm trying to solve a problem of multiple inheritance. It seems to me
> that an interface could be the solution although the interface is
> still a mystery for me.
>
> This is the example code:
>
https://github.com/Blunk-electronic/ada_training/blob/master/src/interfaces_1/interfaces_1.adb

An interface type cannot declare any data: see
http://www.ada-auth.org/standards/2xrm/html/RM-3-9-4.html

So type_c can be:

    type type_C is interface;

and you can define subprograms for type_C, but not data.

-- 
-- Stephe

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

* Re: Simple example on interfaces
  2021-01-25 17:51   ` Mario Blunk
@ 2021-01-25 22:06     ` Dmitry A. Kazakov
  2021-01-26  7:33       ` G.B.
  2021-01-26  9:37       ` J-P. Rosen
  2021-01-26 10:02     ` Stephen Leake
  1 sibling, 2 replies; 28+ messages in thread
From: Dmitry A. Kazakov @ 2021-01-25 22:06 UTC (permalink / raw)


On 2021-01-25 18:51, Mario Blunk wrote:
> 
>> You must define "property." What is it?
> With "property" I mean the selectors like p0, p1 or p2.

They are components or else record members.

>> In your code these types have p2
>> already. Is this static polymorphism not enough?
> It seems so. Suppose there would be more types like C1, D1, ..., each of which derived from type_base, then
> I don't want to define p2 over and over.

There are two different things:

1. interface of a type (in general sense)
2. an implementation of

Ada interface is a type that has interface and no implementation. [It is 
a silly idea inherited from Java.]

So:

- if "define" applies to #1, then yes, you can inherit from Ada 
interface and thus you do not need to "define" inherited primitive 
operations like P2 again.

- if "define" applies to #2, then no, you cannot inherit implementation 
from Ada interface because it can have none.

The first non-abstract type inheriting from an Ada interface must 
implement its interface in full. The types derived from it will inherit 
that implementation. But each sibling as A2 and B1 must implement the 
interface anew.

>> Do you need A2 and B1
>> in a class having p2, with polymorphic objects of the class? Then that
>> would indeed be an interface.
> How would that look like ?

with declarations from the previous post:

    procedure Print_P2 (Object : P2_Interface'Class) is
    begin
       Put ("P2=" & Enum'Image (Object.P2));
    end Print_P2;

    X : A2;
    Y : B1;
begin
    Print_P2 (X);
    Print_P2 (Y);

>> Now, there is no full multiple inheritance in Ada, if p2 must be a
>> component, you are out of luck. You have only one shot and you have
>> spent it on p0 in the type Base.
> That is forbidden as far as the final application is concerned. The example I posted here is a simplification of a more complex scenario.

There exist various dirty tricks to emulate full multiple inheritance 
but no universal solution. If you really need full multiple inheritance, 
choose the most important path of implementations and make types along 
it proper types. Other paths if simple, could tricked using

- Min-in inheritance
- Generic packages to automate implementation of interfaces
- Memory pools to inject implementation

Nothing of these is good. They basically work only if the depths of the 
secondary inheritance paths is 1.

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

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

* Re: Simple example on interfaces
  2021-01-25 22:06     ` Dmitry A. Kazakov
@ 2021-01-26  7:33       ` G.B.
  2021-01-26  8:07         ` Dmitry A. Kazakov
  2021-01-26  9:37       ` J-P. Rosen
  1 sibling, 1 reply; 28+ messages in thread
From: G.B. @ 2021-01-26  7:33 UTC (permalink / raw)


On 25.01.21 23:06, Dmitry A. Kazakov wrote:

>> That is forbidden as far as the final application is concerned. The example I posted here is a simplification of a more complex scenario.
> 
> There exist various dirty tricks to emulate full multiple inheritance but no universal solution. If you really need full multiple inheritance, choose the most important path of implementations and make types along it proper types. Other paths if simple, could tricked using
> 
> - Min-in inheritance
> - Generic packages to automate implementation of interfaces
> - Memory pools to inject implementation
> 
> Nothing of these is good. They basically work only if the depths of the secondary inheritance paths is 1.
> 

(Mix-in inheritance?)

Composition can be a good alternative, too.
It can help making the type graph modular.
It naturally adds separation of concerns.
Is there good reason to prefer Is-A over Has-A?
If all the types are related through inheritance,
will refactoring become easier or harder?

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

* Re: Simple example on interfaces
  2021-01-26  7:33       ` G.B.
@ 2021-01-26  8:07         ` Dmitry A. Kazakov
  2021-01-26  8:17           ` Mario Blunk
  0 siblings, 1 reply; 28+ messages in thread
From: Dmitry A. Kazakov @ 2021-01-26  8:07 UTC (permalink / raw)


On 2021-01-26 08:33, G.B. wrote:

> Composition can be a good alternative, too.

Composition was the starting point. See the original post.

> It can help making the type graph modular.

By modular by mean disconnected? But the question was to make it 
connected by removing duplicated nodes.

> It naturally adds separation of concerns.
> Is there good reason to prefer Is-A over Has-A?

It is not a question of preference, it either fallacy (when set in mixed 
with a member of) or else different interfaces, like record type 
interface vs. some other interface.

> If all the types are related through inheritance,
> will refactoring become easier or harder?

You meant reuse, probably. Composition was zero re-use beyond your 
editor's clipboard support of cut-and-paste.

As for logical relationships between types, usually such things are 
influenced by the problem space. The question of design to map these by 
language types.

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

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

* Re: Simple example on interfaces
  2021-01-26  8:07         ` Dmitry A. Kazakov
@ 2021-01-26  8:17           ` Mario Blunk
  2021-01-26  8:55             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 28+ messages in thread
From: Mario Blunk @ 2021-01-26  8:17 UTC (permalink / raw)


Dmitry,
thanks for your help. I reordered things in the example. The outcome can be seen here:
https://github.com/Blunk-electronic/ada_training/tree/master/src/interfaces

But as you already said, p2 can not be a real record element as we can see in
https://github.com/Blunk-electronic/ada_training/blob/master/src/interfaces/lib/pac_1.adb
There is no source to fetch the "content" of p2 as there is no element p2.

Perhaps I did not understand your approach completely.
I think I should abandon the idea to solve the problem with an interface.

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

* Re: Simple example on interfaces
  2021-01-26  8:17           ` Mario Blunk
@ 2021-01-26  8:55             ` Dmitry A. Kazakov
  0 siblings, 0 replies; 28+ messages in thread
From: Dmitry A. Kazakov @ 2021-01-26  8:55 UTC (permalink / raw)


On 2021-01-26 09:17, Mario Blunk wrote:

> thanks for your help. I reordered things in the example. The outcome can be seen here:
> https://github.com/Blunk-electronic/ada_training/tree/master/src/interfaces
> 
> But as you already said, p2 can not be a real record element as we can see in
> https://github.com/Blunk-electronic/ada_training/blob/master/src/interfaces/lib/pac_1.adb
> There is no source to fetch the "content" of p2 as there is no element p2.
> 
> Perhaps I did not understand your approach completely.

You must provide an implementation for P2:

    type A2 is new A1 and P2_Interface with private;
    overriding function P2 (Object : A2) return Enum;

    type B1 is new Base and P2_Interface with private;
    overriding function P2 (Object : B1) return Enum;

private
    type A2 is new A1 and P2_Interface with record
       P2_Implementation : Enum;
    end record;

    type B1 is new Base and P2_Interface with record
       P2_Implementation : Enum;
    end record;

You cannot re-use this implementation. Here you re-use the interface only.

There are tricks to re-use implementation as well. As I said I would not 
recommend them.

Anyway, for example, this is how generics can be used to hang an 
interface on a type.

generic
    type Victim is abstract new Base with private;
package Generic_Add_P2 is
    type Victim_With_P2 is
       abstract new Victim and P2_Interface with private;
    overriding function P2 (Object : Victim_With_P2) return Enum;
private
    type Victim_With_P2 is new Victim and P2_Interface with record
       P2_Implementation : Enum;
    end record;
end Generic_Add_P2;

package body Generic_Add_P2 is
    function P2 (Object : Victim_With_P2) return Enum is
    begin
       return Object.P2_Implementation;
    end P2;
end Generic_Add_P2;

package Do_A2 is new Generic_Add_P2 (A1);
type A2 is new Do_A2.Victim_With_P2 with record
    -- other members
end record;

package Do_B1 is new Generic_Add_P2 (Base);
type B1 is new Do_B1.Victim_With_P2 with record
    -- other members
end record;

You can extend that to have a setter as well.

It might even be possible to achieve the getter/setter's syntax to

    X := A2.P2;
    A2.P2 := Low;

rather than

    X := A2.P2;
    Set (A2, Low);

But I am too lazy to figure it out, as it would require dozens of helper 
and access types. I never use this horrific new Ada 2012+ stuff. Maybe 
someone else might help...

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

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

* Re: Simple example on interfaces
  2021-01-25 22:06     ` Dmitry A. Kazakov
  2021-01-26  7:33       ` G.B.
@ 2021-01-26  9:37       ` J-P. Rosen
  2021-01-26 10:25         ` Dmitry A. Kazakov
  1 sibling, 1 reply; 28+ messages in thread
From: J-P. Rosen @ 2021-01-26  9:37 UTC (permalink / raw)


Le 25/01/2021 à 23:06, Dmitry A. Kazakov a écrit :
> Ada interface is a type that has interface and no implementation. [It is 
> a silly idea inherited from Java.]
> 
To make it look a little less silly, think of it as a promise: a type 
that implements an interface promises to provide a certain number of 
operations.

Then you can define algorithms that work on any type that fulfills the 
promises.

To me, the big benefit of interfaces is that it is NOT inheritance; you 
say that your type provides some operations, without needing to classify 
it with an is-a relationship.

(I can hear screamings of pure-OO people who will not agree with me ;-) )

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr

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

* Re: Simple example on interfaces
  2021-01-25 17:51   ` Mario Blunk
  2021-01-25 22:06     ` Dmitry A. Kazakov
@ 2021-01-26 10:02     ` Stephen Leake
  1 sibling, 0 replies; 28+ messages in thread
From: Stephen Leake @ 2021-01-26 10:02 UTC (permalink / raw)


Mario Blunk <marioblunk.alere@gmail.com> writes:

>> (I removed annoying "type_" prefix from all types) 
> I got used to this notation in order to avoid confusion between a type
> and a variable. Not important here.

Another way to solve this problem is to prefix the package name when necessary.

-- 
-- Stephe

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

* Re: Simple example on interfaces
  2021-01-26  9:37       ` J-P. Rosen
@ 2021-01-26 10:25         ` Dmitry A. Kazakov
  2021-01-26 11:15           ` AdaMagica
  0 siblings, 1 reply; 28+ messages in thread
From: Dmitry A. Kazakov @ 2021-01-26 10:25 UTC (permalink / raw)


On 2021-01-26 10:37, J-P. Rosen wrote:
> Le 25/01/2021 à 23:06, Dmitry A. Kazakov a écrit :
>> Ada interface is a type that has interface and no implementation. [It 
>> is a silly idea inherited from Java.]
>>
> To make it look a little less silly, think of it as a promise: a type 
> that implements an interface promises to provide a certain number of 
> operations.

I agree. I meant that Ada 95 had that already:

    type Interface is abstract tagged null record;

There was no need to introduce it as a separate concept. I think the 
real reason was laziness. Vendors did not want to implement full 
multiple inheritance. Adding a simple constraint on the base types 
looked bad and also breached privacy:

    type Is_It_Interface is abstract tagged private;
private
    type Is_It_Interface is abstract tagged null record;

> Then you can define algorithms that work on any type that fulfills the 
> promises.
> 
> To me, the big benefit of interfaces is that it is NOT inheritance; you 
> say that your type provides some operations, without needing to classify 
> it with an is-a relationship.

But you do. When you say that T provides F that in other words means T 
*is-a* member of a class that provides F. Interface is merely a 
formalization of that.

> (I can hear screamings of pure-OO people who will not agree with me ;-) )

OO muddied a lot of water. To me things are quite pragmatic. How do I 
spell in the language the fact that Long_Integer is an integer? If 
Integer is an integer and Long_Integer is an integer can I write a 
program that works on integers? Can it be the *same* program for each 
instance of? Simple, natural questions.

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

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

* Re: Simple example on interfaces
  2021-01-26 10:25         ` Dmitry A. Kazakov
@ 2021-01-26 11:15           ` AdaMagica
  2021-01-26 11:53             ` Dmitry A. Kazakov
  0 siblings, 1 reply; 28+ messages in thread
From: AdaMagica @ 2021-01-26 11:15 UTC (permalink / raw)


Dmitry A. Kazakov schrieb am Dienstag, 26. Januar 2021 um 11:25:41 UTC+1:
> How do I 
> spell in the language the fact that Long_Integer is an integer? If 
> Integer is an integer and Long_Integer is an integer can I write a 
> program that works on integers? Can it be the *same* program for each 
> instance of? Simple, natural questions.

This is what generics are for (since Ada 83).

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

* Re: Simple example on interfaces
  2021-01-26 11:15           ` AdaMagica
@ 2021-01-26 11:53             ` Dmitry A. Kazakov
  2021-01-26 16:46               ` AdaMagica
  0 siblings, 1 reply; 28+ messages in thread
From: Dmitry A. Kazakov @ 2021-01-26 11:53 UTC (permalink / raw)


On 2021-01-26 12:15, AdaMagica wrote:
> Dmitry A. Kazakov schrieb am Dienstag, 26. Januar 2021 um 11:25:41 UTC+1:
>> How do I
>> spell in the language the fact that Long_Integer is an integer? If
>> Integer is an integer and Long_Integer is an integer can I write a
>> program that works on integers? Can it be the *same* program for each
>> instance of? Simple, natural questions.
> 
> This is what generics are for (since Ada 83).

Right, generics is a form of polymorphism (static one). Generics have 
interfaces and these form classes.

The problem with generics (static polymorphism which also includes 
overloading) is that they answer no to the last question. There cannot 
be same program because there is no class-wide (polymorphic) objects 
from the generics' class.

P.S. Comparing generics to overloading, generics offer some re-use, and 
some degree of formalization at the cost of producing huge mess, while 
overloading does none.

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

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

* Re: Simple example on interfaces
  2021-01-26 11:53             ` Dmitry A. Kazakov
@ 2021-01-26 16:46               ` AdaMagica
  2021-01-26 19:44                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 28+ messages in thread
From: AdaMagica @ 2021-01-26 16:46 UTC (permalink / raw)


Dmitry A. Kazakov schrieb am Dienstag, 26. Januar 2021 um 12:53:25 UTC+1:
> The problem with generics (static polymorphism which also includes
> overloading) is that they answer no to the last question. There cannot
> be same program because there is no class-wide (polymorphic) objects
> from the generics' class.

universal_integer being something like class of all integers, this would be:

generic
  type T is range <>;
procedure F (X: T);

is replaced by the classwide

procedure F (X: universal_integer);  -- not Ada

universal_integer is anonymous and doesn't have any operations (except automatic conversion).

> P.S. Comparing generics to overloading, generics offer some re-use, and
> some degree of formalization at the cost of producing huge mess, while
> overloading does none.

I know you don't like generics. I do not see a huge mess.

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

* Re: Simple example on interfaces
  2021-01-26 16:46               ` AdaMagica
@ 2021-01-26 19:44                 ` Dmitry A. Kazakov
  2021-01-26 20:04                   ` Shark8
  2021-01-27  3:09                   ` Randy Brukardt
  0 siblings, 2 replies; 28+ messages in thread
From: Dmitry A. Kazakov @ 2021-01-26 19:44 UTC (permalink / raw)


On 2021-01-26 17:46, AdaMagica wrote:
> Dmitry A. Kazakov schrieb am Dienstag, 26. Januar 2021 um 12:53:25 UTC+1:
>> The problem with generics (static polymorphism which also includes
>> overloading) is that they answer no to the last question. There cannot
>> be same program because there is no class-wide (polymorphic) objects
>> from the generics' class.
> 
> universal_integer being something like class of all integers, this would be:

Maybe class, maybe parent (cloned upon type X is new Y constructs).

> generic
>    type T is range <>;
> procedure F (X: T);
> 
> is replaced by the classwide
> 
> procedure F (X: universal_integer);  -- not Ada

Or, maybe

    procedure F (X: universal_integer'Class);  -- not Ada

> universal_integer is anonymous and doesn't have any operations (except automatic conversion).

Yes. In a never ending discussion with Randy I insist that this stuff 
should be made explicit, available for any types.

>> P.S. Comparing generics to overloading, generics offer some re-use, and
>> some degree of formalization at the cost of producing huge mess, while
>> overloading does none.
> 
> I know you don't like generics. I do not see a huge mess.

When something goes wrong it is almost impossible to figure what. 
Contracts are mostly implicit. They are not enforced upon compilation. 
Instantiation errors nobody can really predict. On top of that is 
uncontrollable name space pollution.

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

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

* Re: Simple example on interfaces
  2021-01-26 19:44                 ` Dmitry A. Kazakov
@ 2021-01-26 20:04                   ` Shark8
  2021-01-26 21:34                     ` Dmitry A. Kazakov
  2021-01-27  3:11                     ` Randy Brukardt
  2021-01-27  3:09                   ` Randy Brukardt
  1 sibling, 2 replies; 28+ messages in thread
From: Shark8 @ 2021-01-26 20:04 UTC (permalink / raw)


On Tuesday, January 26, 2021 at 12:44:45 PM UTC-7, Dmitry A. Kazakov wrote:
> Instantiation errors nobody can really predict. On top of that is 
> uncontrollable name space pollution.
I submitted an AI that solves a lot of the pollution:
http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0268-1.txt?rev=1.3&raw=N

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

* Re: Simple example on interfaces
  2021-01-26 20:04                   ` Shark8
@ 2021-01-26 21:34                     ` Dmitry A. Kazakov
  2021-01-27  3:11                     ` Randy Brukardt
  1 sibling, 0 replies; 28+ messages in thread
From: Dmitry A. Kazakov @ 2021-01-26 21:34 UTC (permalink / raw)


On 2021-01-26 21:04, Shark8 wrote:
> On Tuesday, January 26, 2021 at 12:44:45 PM UTC-7, Dmitry A. Kazakov wrote:
>> Instantiation errors nobody can really predict. On top of that is
>> uncontrollable name space pollution.
> I submitted an AI that solves a lot of the pollution:
> http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0268-1.txt?rev=1.3&raw=N

Well, it would have only limited use.

The case you present is rather solved by using child generics as they 
"inherit" parameters. So

    generic
    package Generic_Swap.Generic_Stack is

And here we come to the real-world problem. Generic packages and their 
formal parameters are organized in a directed acyclic graph like:

     A   D
    / \ /|
   B   C |
    \ /  |
     E   |
      \ /
       F

rather than a tree. You want to instantiate the whole graph in a single 
shot. You do not want to manually specify constraints on generic formal 
parameters when some of them travel by several paths as D into F.

BTW, observe similarity with diamond/rhombus MI. That MI has some 
problems generics do not have is a big lie.

But in my view generics are beyond salvation. The idea is inherently 
weakly typed. Ada's generic contracts are too loose to be safe and too 
rigid for usability of C++ templates.

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

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

* Re: Simple example on interfaces
  2021-01-25 17:00 ` Jeffrey R. Carter
@ 2021-01-27  1:48   ` philip...@gmail.com
  2021-01-27  8:06     ` Dmitry A. Kazakov
  2021-01-27  3:36   ` Randy Brukardt
  1 sibling, 1 reply; 28+ messages in thread
From: philip...@gmail.com @ 2021-01-27  1:48 UTC (permalink / raw)


> "IMHO, Interfaces are worthless." 

I find interfaces to be extremely valuable for abstracting I/O devices.  For example in my Linux Simple I/O Library, there is code equivalent to the following (the actual code is different, as I sucked a lot of common boilerplate for I/O device interfaces into a generic package that is instantiated for each data item type):

package GPIO is

  type Direction is (Input, Output);
  type PinInterface is interface;
  type Pin is access all PinInterface'Class;

  procedure Put(Self : PinInterface; state : Boolean);

  function Get(Self : PinInterface) return Boolean;
end GPIO;

I've probably defined a dozen packages that implement GPIO pins using everything from Linux kernel services to web servers.  Every one of them contains a function like this:

  function Create(...) return GPIO.Pin;

This allows code like the following:

  GPIO1 : GPIO.Pin := GPIO.libsimpleio.Create(RaspberryPi.GPIO18, GPIO.Output);
  GPIO2 : GPIO.Pin := GPIO.HTTP.Create("http://foo.munts.net", 5, GPIO.Output);
  GPIO3 : GPIO.Pin := GPIO.RemoteIO.Create(server, 7, GPIO.Output);

This allows GPIO pins scattered far and near throughout the known universe to be treated exactly the same, even collected into an array or container.

I very seldom implement more than one interface in a type definition though, unless a single device has multiple sensors (temperature and humidity, for instance).

Microsoft's .Net uses this scheme pervasively, though I originally learned it in Ada and later applied the same thinking to .Net, Free Pascal, Java, Python, and C++ (and other languages).

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

* Re: Simple example on interfaces
  2021-01-26 19:44                 ` Dmitry A. Kazakov
  2021-01-26 20:04                   ` Shark8
@ 2021-01-27  3:09                   ` Randy Brukardt
  2021-01-27  8:05                     ` Dmitry A. Kazakov
  1 sibling, 1 reply; 28+ messages in thread
From: Randy Brukardt @ 2021-01-27  3:09 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:ruprf8$1h6q$1@gioia.aioe.org...
...
>> universal_integer is anonymous and doesn't have any operations (except 
>> automatic conversion).
>
> Yes. In a never ending discussion with Randy I insist that this stuff 
> should be made explicit, available for any types.

As I've often said, for a new language that would certainly be a good idea. 
For Ada, reproducing all of the quirks of Ada would lead to an inpentrable 
mess. And not reproducing them would break a lot of code (and more 
importantly, no one could tell if their code would be broken and in extreme 
cases, wouldn't even know as the code would silently change meaning).

As far as full multiple inheritance being too expensive to implement, I tend 
to think that is true for interfaces as well. :-) As always, the question is 
whether one wants fast code or just something that works. Full multiple 
inheritance certainly can be implemented by converting all selectors to 
Getter/Setter pairs and dispatching on every use. But that's pretty 
expensive for accessing an integer component. Of course, most of the time it 
won't matter (Janus/Ada does something like this for shared generics, and I 
have yet to have someone complain about performance of generic code). But 
there will be cases where it does matter, and this is a distributed 
overhead -- it applies to all types whether or not you use it (because 
someone could extend this type in some future unit not even written yet).

                                        Randy.


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

* Re: Simple example on interfaces
  2021-01-26 20:04                   ` Shark8
  2021-01-26 21:34                     ` Dmitry A. Kazakov
@ 2021-01-27  3:11                     ` Randy Brukardt
  2021-01-27 22:51                       ` Shark8
  1 sibling, 1 reply; 28+ messages in thread
From: Randy Brukardt @ 2021-01-27  3:11 UTC (permalink / raw)


"Shark8" <onewingedshark@gmail.com> wrote in message 
news:d2ad937c-7b15-4766-aa88-c0a9ce474f0bn@googlegroups.com...
> On Tuesday, January 26, 2021 at 12:44:45 PM UTC-7, Dmitry A. Kazakov 
> wrote:
>> Instantiation errors nobody can really predict. On top of that is
>> uncontrollable name space pollution.
> I submitted an AI that solves a lot of the pollution:
> http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0268-1.txt?rev=1.3&raw=N

Whatever happened to your ARG participation, anyway? You just sort of 
disappeared...

                   Randy.


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

* Re: Simple example on interfaces
  2021-01-25 17:00 ` Jeffrey R. Carter
  2021-01-27  1:48   ` philip...@gmail.com
@ 2021-01-27  3:36   ` Randy Brukardt
  2021-01-27 23:04     ` Shark8
  1 sibling, 1 reply; 28+ messages in thread
From: Randy Brukardt @ 2021-01-27  3:36 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:rumtg6$j94$1@dont-email.me...
> On 1/25/21 5:08 PM, Mario Blunk wrote:
>> I'm trying to solve a problem of multiple inheritance. It seems to me 
>> that an interface could be the solution although the interface is still a 
>> mystery for me.
>
> "IMHO, Interfaces are worthless."
> Randy Brukardt

To qualify that a bit, they're worthless to me (and I suspect, most people). 
For me, at least, OOP's benefits are mainly found in implementation 
inheritance, which is not available for Interfaces. You have to use abstract 
types to get those benefits.

For a single program, an interface doesn't buy anything, because it is very 
unlikely that you'll have more than one implementation of the interface in 
use. (Think the queue interface in Annex A.) So using dispatching just adds 
complication but no benefit; most likely you'll statically bind everything 
anyway.

Which pretty much leaves reusuable code. Here, dispatching probably does 
have some benefit. But you can get similar benefits from generic units with 
formal derived type parameters. The problem is that interface dispatching is 
quite expensive (not just the indexing of single inheritance dispatching, 
but also some sort of lookup of the appropriate table). Whereas the generic 
solution does most of the binding at compile-time.

It may be my optimizer guru background, but indirect calls are pretty much 
unoptimizable. Ergo, the cost of dispatching is even worse than it appears 
on the surface, given that valuable optimizations like inlining, partial 
evaluation (currying), and all of the things that they enable aren't 
possible. So if the code performance matters, ultimately the interfaces will 
have to go. (Of course, if it *doesn't* matter, one shouldn't be warping a 
design for performance reasons. But it is *hard* to get rid of interfaces 
that are too expensive, so I think it makes most sense to be sparing with 
their use.)

Ultimately, I think one should only use interfaces IFF there is a clear 
reuse case where the substantial cost of dispatching is not a concern. For 
me, that is approximately never, but of course your mileage may vary.

                                               Randy.


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

* Re: Simple example on interfaces
  2021-01-27  3:09                   ` Randy Brukardt
@ 2021-01-27  8:05                     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 28+ messages in thread
From: Dmitry A. Kazakov @ 2021-01-27  8:05 UTC (permalink / raw)


On 2021-01-27 04:09, Randy Brukardt wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:ruprf8$1h6q$1@gioia.aioe.org...
> ...
>>> universal_integer is anonymous and doesn't have any operations (except
>>> automatic conversion).
>>
>> Yes. In a never ending discussion with Randy I insist that this stuff
>> should be made explicit, available for any types.
> 
> As I've often said, for a new language that would certainly be a good idea.
> For Ada, reproducing all of the quirks of Ada would lead to an inpentrable
> mess. And not reproducing them would break a lot of code (and more
> importantly, no one could tell if their code would be broken and in extreme
> cases, wouldn't even know as the code would silently change meaning).

Universal_Integer is already implemented in all existing compilers.

> As far as full multiple inheritance being too expensive to implement, I tend
> to think that is true for interfaces as well. :-) As always, the question is
> whether one wants fast code or just something that works. Full multiple
> inheritance certainly can be implemented by converting all selectors to
> Getter/Setter pairs and dispatching on every use. But that's pretty
> expensive for accessing an integer component.

Same. All this is already there and implemented. The question is why is 
it not formalized in the language?

Consider this Ada 83:

    Jagged : array (1..100) of String;

This is valid construct though not allowed (someone like you said it 
would be too expensive to implement).

OK, do not implement it, but at least allow to spell the concept of an 
array of strings!

What you say is that I cannot have an array of integers because arrays 
of strings is so useless, dangerous and mess, would require to design a 
new language etc. I did not asked arrays of strings, so far... (:-))

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

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

* Re: Simple example on interfaces
  2021-01-27  1:48   ` philip...@gmail.com
@ 2021-01-27  8:06     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 28+ messages in thread
From: Dmitry A. Kazakov @ 2021-01-27  8:06 UTC (permalink / raw)


On 2021-01-27 02:48, philip...@gmail.com wrote:
>> "IMHO, Interfaces are worthless."
> 
> I find interfaces to be extremely valuable for abstracting I/O devices.

Operating systems always were OO. It is impossible to design something 
like interrupt handler without dispatching. Interrupts are dispatching.

The question is never interfaces or not. It is how much language support 
I can get.

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

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

* Re: Simple example on interfaces
  2021-01-27  3:11                     ` Randy Brukardt
@ 2021-01-27 22:51                       ` Shark8
  2021-01-30  8:33                         ` Randy Brukardt
  0 siblings, 1 reply; 28+ messages in thread
From: Shark8 @ 2021-01-27 22:51 UTC (permalink / raw)


On Tuesday, January 26, 2021 at 8:11:14 PM UTC-7, Randy Brukardt wrote:
> "Shark8" wrote in message 
> > I submitted an AI that solves a lot of the pollution: 
> > http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0268-1.txt?rev=1.3&raw=N
> Whatever happened to your ARG participation, anyway? You just sort of 
> disappeared... 

2020 was *not* a good year for me; after being holed up on-site for 8 months and seeing less than a dozen people I found the meaning of "cabin fever" -- I'm just glad I didn't get back to my 2015–17 levels of depression.
I think I have to re-type what I had on the AI that 0268-1 was rolled into, but I had some ideas for allowing the automatic-instantiation to have a name generated by it's location.

If I can remember to bring my wallet into work tomorrow, I'll give you a call and place an order for a personal copy of Janus/Ada.

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

* Re: Simple example on interfaces
  2021-01-27  3:36   ` Randy Brukardt
@ 2021-01-27 23:04     ` Shark8
  0 siblings, 0 replies; 28+ messages in thread
From: Shark8 @ 2021-01-27 23:04 UTC (permalink / raw)


On Tuesday, January 26, 2021 at 8:36:56 PM UTC-7, Randy Brukardt wrote:
> 
> Ultimately, I think one should only use interfaces IFF there is a clear 
> reuse case where the substantial cost of dispatching is not a concern. For 
> me, that is approximately never, but of course your mileage may vary. 

It makes sense to use them in the internals of the compiler. Perhaps not a single-language compiler, but certainly a multilanguage one like GCC. An argument could be made for a single-language compiler in an environment like described in the DIANA reference-manual's rationale, where the DIANA-structure was meant to be passed around to things like pretty-printers and static-analyzers and code-generators.

You could make an argument that it would be useful for code-generators, too.
I was contemplating using something like a hybrid of IEEE694 and 3AC last year... but that's a bit of a tangent.

https://standards.ieee.org/standard/694-1985.html
3AC = Three Address Code

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

* Re: Simple example on interfaces
  2021-01-27 22:51                       ` Shark8
@ 2021-01-30  8:33                         ` Randy Brukardt
  0 siblings, 0 replies; 28+ messages in thread
From: Randy Brukardt @ 2021-01-30  8:33 UTC (permalink / raw)


"Shark8" <onewingedshark@gmail.com> wrote in message 
news:f2bf8a63-4539-4c1e-a433-6556dcd642bbn@googlegroups.com...
...
>If I can remember to bring my wallet into work tomorrow, I'll give you a 
>call
>and place an order for a personal copy of Janus/Ada.

I've been working at home as much as possible during the pandemic, so I 
didn't see this or get your messages until now (I'm still coming into the 
office to do the weekly backups on Friday evenings). I'll try to get back to 
you on Monday.

                      Randy.


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

end of thread, other threads:[~2021-01-30  8:33 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-25 16:08 Simple example on interfaces Mario Blunk
2021-01-25 16:41 ` Dmitry A. Kazakov
2021-01-25 17:51   ` Mario Blunk
2021-01-25 22:06     ` Dmitry A. Kazakov
2021-01-26  7:33       ` G.B.
2021-01-26  8:07         ` Dmitry A. Kazakov
2021-01-26  8:17           ` Mario Blunk
2021-01-26  8:55             ` Dmitry A. Kazakov
2021-01-26  9:37       ` J-P. Rosen
2021-01-26 10:25         ` Dmitry A. Kazakov
2021-01-26 11:15           ` AdaMagica
2021-01-26 11:53             ` Dmitry A. Kazakov
2021-01-26 16:46               ` AdaMagica
2021-01-26 19:44                 ` Dmitry A. Kazakov
2021-01-26 20:04                   ` Shark8
2021-01-26 21:34                     ` Dmitry A. Kazakov
2021-01-27  3:11                     ` Randy Brukardt
2021-01-27 22:51                       ` Shark8
2021-01-30  8:33                         ` Randy Brukardt
2021-01-27  3:09                   ` Randy Brukardt
2021-01-27  8:05                     ` Dmitry A. Kazakov
2021-01-26 10:02     ` Stephen Leake
2021-01-25 17:00 ` Jeffrey R. Carter
2021-01-27  1:48   ` philip...@gmail.com
2021-01-27  8:06     ` Dmitry A. Kazakov
2021-01-27  3:36   ` Randy Brukardt
2021-01-27 23:04     ` Shark8
2021-01-25 19:05 ` Stephen Leake

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