From: Dmitry A. Kazakov on
On Thu, 14 Jan 2010 10:01:48 -0800 (PST), Shark8 wrote:

>>>> There shall be no interfaces at all. Ada 95 had everything needed, i.e.
>>>> abstract types. Introducing interfaces in Ada 2005 was a huge mistake.
>>
>>> Why do you say that?
>>
>> Because there should be a honest MI and no interfaces.
>
> But Ada doesn't support honest MI. How do you propose to work-around/
> implement that?

By changing the language standard, of course. (:-))

> Furthermore, what sort of system would you use to
> solve the diamond problem?

I don't need to solve it. It is firstly not a problem and secondly it
perfectly exists in interfaces:

type A is interface;
procedure F (X : A) is abstract;
type B is interface and A;
type C is interface and A;
type D is interface and B and C;

It also does in packages (with/use) and many other cases.

>> You do not need explicitly named contracts in a language like Ada. The
>> contract of a type is the type itself.
>
> Agreed, you could define all the operations of both inherited types,
> have them as mix-in components, and handle things that way. That
> method however excludes the option of saying something like "if Hybrid
> in Clothing.Button" and "if hybrid in UI.Button" at the same time (you
> could inherit from one and then be able to use one of the above,
> true).

Use T'Class with membership test S in T'Class.

(It is a bit sloppy that Ada uses "in" both for S in T and for S in
T'Class. In mathematics membership and subset are two distinct relations)

>> Ada has type declarations, public and private. Everything visible related to the type is the contract of.
>> Period.
>
> I agree that everything visible is the [ultimate] contract of the
> type. However I don't see why having an interface is any different
> than having as an inheritance-base a fully abstract object. Can you
> explain how you see it as such then?

Why do I need interface? What does it add to

type T is abstract private;

existed in Ada 95. (Answer: it adds a new reserved word! (:-))

>> Rather than *in advance* trying to declare all possible interfaces. It is
>> awful and leads to an explosion of meaningless declarations like:
>>
>> � �type T_Interface is interface ... ; -- Just in case we would need it!
>> � �procedure Foo (X : T_Interface) is abstract;
>> � �type T is new T_Interface with ...; -- No we starting to work
>> � �overriding procedure Foo (X : T);
>>
>> That is a mess and a maintenance disaster.
>
> That sounds like a bad idea, true. But isn't it also an exercise in
> misdesign to throw in "just in case we need it" haphazardly?

If you have a large system, you never know in advance. The code like above
is from a real project. We are probably in a minority who actively deploy
Ada 2005 features. We have a lot of interfaces and more we have them, less
we enjoy them. He have approximately 20-30% of utterly meaningless cut and
pasted code because of lack of MI. As a trivial example consider:

type Read_File is limited interface;
procedure Read (File : in out Read_File; ...) is abstract;

type Write_File is limited interface;
procedure Write (File : in out Write_File; ...) is abstract;

type Read_Write_File is limited interface and Read_File and Write_File;

How consider how would you implement these somewhere at the bottom of a
hierarchy of concrete file types. Add there some other inheritance axis
like handles to files, different contents, different devices (here you will
badly need MD, but that is another story). Then observe how code
duplication propagates from the bottom up all the inheritance levels
multiplying itself at each. This is customary fought using generics which
crown the mess.

>> Sure. Translated to OO: FS is a specialized persistent container library.
>
> Excellent. Why then would it be a bad idea to support FS-in-the-
> abstract considering that currently [virtually] everyone's data is in
> one instance or another of this "specialized persistent container
> library"?

Surely it is.

> It would make things easier from the migration-to
> standpoint.

It would not, because the difference is not in a tree-like structure of
named elements, but in the types of those elements.

>>>>>> Without MI, MD, tagged tasks, there is no chance to get
>>>>>> it right.
>
> Couldn't we emulate tagged tasks [to some degree] by having a "Tag"
> entry with an output parameter giving the tag?

You have to be able to derive from a task, that is what active objects are.
BTW, you already can do this in Ada 2005. It has task interfaces, but this
inheritance is limited to have the depth of 1.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Georg Bauhaus on
On 1/14/10 8:19 PM, Dmitry A. Kazakov wrote:
> On Thu, 14 Jan 2010 18:57:24 +0000 (UTC), tmoran(a)acm.org wrote:

>> If you
>> want to do a virus scan on a .vob file, it's not a video file - it's
>> a series of bytes.
>
> I don't need to scan for viruses an object which single operation is play
> (takes the device context as the second parameter).

You'd need to scan the video for hidden espionage data,
or for a hidden message that if delivered will save a life.

You'd need to scan the video for information related to color,
brightness, etc. when adjusting cinema equipment to
current weather conditions.

Do all these operations need to override "play" accordingly,
or are you thinking of using Cartesian product types created
as needed, maybe?
Will all persistent video objects be extensible so that they can
provide the necessary subprograms that some use case needs?

From: Shark8 on
> >>> Why do you say that?
>
> >> Because there should be a honest MI and no interfaces.
>
> > But Ada doesn't support honest MI. How do you propose to work-around/
> > implement that?
>
> By changing the language standard, of course. (:-))

Ah, but this brings up a question: HOW do we change it?

> > Furthermore, what sort of system would you use to
> > solve the diamond problem?
>
> I don't need to solve it. It is firstly not a problem and secondly it
> perfectly exists in interfaces:
>
>    type A is interface;
>    procedure F (X : A) is abstract;
>    type B is interface and A;
>    type C is interface and A;
>    type D is interface and B and C;
>
> It also does in packages (with/use) and many other cases.

But isn't B.F exactly equal to C.F in that we're using an inherited
procedure/function? The diamond problem is about components named the
same that have different types... because interfaces ARE abstract
objects (with the further restriction that they are denied fields)
they don't suffer from the diamond problem. {That is the footprint of
Procedure Foo is EXACTLY the same in all three, they are all the
same.}

> >> You do not need explicitly named contracts in a language like Ada. The
> >> contract of a type is the type itself.
>
> > Agreed, you could define all the operations of both inherited types,
> > have them as mix-in components, and handle things that way. That
> > method however excludes the option of saying something like "if Hybrid
> > in Clothing.Button" and "if hybrid in UI.Button" at the same time (you
> > could inherit from one and then be able to use one of the above,
> > true).
>
> Use T'Class with membership test S in T'Class.

You're right I forgot the 'Class. But the problem still stands with it
rewritten as such.

> (It is a bit sloppy that Ada uses "in" both for S in T and for S in
> T'Class. In mathematics membership and subset are two distinct relations)

True. But if we're talking about an OO hierarchy then a derived-member
of some class IS a superset of that class; and also as things fall
into a nice hiearchy, we see that these classes themselves are sets.

> Why do I need interface? What does it add to
>
>    type T is abstract private;
>
> existed in Ada 95. (Answer: it adds a new reserved word! (:-))

LOL

> >> Rather than *in advance* trying to declare all possible interfaces. It is
> >> awful and leads to an explosion of meaningless declarations like:
>
> >>    type T_Interface is interface ... ; -- Just in case we would need it!
> >>    procedure Foo (X : T_Interface) is abstract;
> >>    type T is new T_Interface with ...; -- No we starting to work
> >>    overriding procedure Foo (X : T);
>
>
> If you have a large system, you never know in advance. The code like above
> is from a real project. We are probably in a minority who actively deploy
> Ada 2005 features. We have a lot of interfaces and more we have them, less
> we enjoy them. He have approximately 20-30% of utterly meaningless cut and
> pasted code because of lack of MI. As a trivial example consider:
>
>    type Read_File is limited interface;
>    procedure Read (File : in out Read_File; ...) is abstract;
>
>    type Write_File is limited interface;
>    procedure Write (File : in out Write_File; ...) is abstract;
>
>    type Read_Write_File is limited interface and Read_File and Write_File;

I think it points to a bad design. IMO, I think something like this
would be in order:

Type Abstract_File is limited interface;
-- All abstractable file operations go here.
Function Readable( File : in Abstract_File ) return Boolean is
Abstract;
Function Writable( File : in Abstract_File ) return Boolean is
Abstract;
Procedure Read ( File : in Abstract_File; Stream :
Stream_Class'Class ) is Abstract;
Procedure Write( File : in Abstract_File; Stream :
Stream_Class'Class ) is Abstract;
-- And so forth.

> How consider how would you implement these somewhere at the bottom of a
> hierarchy of concrete file types. Add there some other inheritance axis
> like handles to files, different contents, different devices (here you will
> badly need MD, but that is another story). Then observe how code
> duplication propagates from the bottom up all the inheritance levels
> multiplying itself at each. This is customary fought using generics which
> crown the mess.
>
> >> Sure. Translated to OO: FS is a specialized persistent container library.
>
> > Excellent. Why then would it be a bad idea to support FS-in-the-
> > abstract considering that currently [virtually] everyone's data is in
> > one instance or another of this "specialized persistent container
> > library"?
>
> Surely it is.

That doesn't answer the WHY question.

> > It would make things easier from the migration-to
> > standpoint.
>
> It would not, because the difference is not in a tree-like structure of
> named elements, but in the types of those elements.

Um, are you forgetting the librarian/library/book metaphor from
earlier? The FILE is like the book, it's type is a property of the
abstract-type "book," the Library is the physical drive where you go
to get said book, the librarian is the one who knows how to traverse
the organization/disorganization within the library is the FS. (Not
all FSes are Hierarchical, think of them as some ADT holding some
File'Class objects.)

> >>>>>> Without MI, MD, tagged tasks, there is no chance to get
> >>>>>> it right.
>
> > Couldn't we emulate tagged tasks [to some degree] by having a "Tag"
> > entry with an output parameter giving the tag?
>
> You have to be able to derive from a task, that is what active objects are.
> BTW, you already can do this in Ada 2005. It has task interfaces, but this
> inheritance is limited to have the depth of 1.

I remember reading that now... but is an inheritance level of 1 good
enough? Possibly if we were to abstract things in the correct manner.
If the inheritance level is one, is it also legal to have task types
Abstract_Program and Abstract_something which are both implemented in
a single class/case? {It would have the requisite depth of 1...}
From: Dmitry A. Kazakov on
On Thu, 14 Jan 2010 21:33:25 +0100, Georg Bauhaus wrote:

> On 1/14/10 8:19 PM, Dmitry A. Kazakov wrote:
>> On Thu, 14 Jan 2010 18:57:24 +0000 (UTC), tmoran(a)acm.org wrote:
>
>>> If you
>>> want to do a virus scan on a .vob file, it's not a video file - it's
>>> a series of bytes.
>>
>> I don't need to scan for viruses an object which single operation is play
>> (takes the device context as the second parameter).
>
> You'd need to scan the video for hidden espionage data,
> or for a hidden message that if delivered will save a life.

If you cannot scan it, how are you going to get the message from? (:-))

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Dmitry A. Kazakov on
On Thu, 14 Jan 2010 13:07:08 -0800 (PST), Shark8 wrote:

>>>>> Why do you say that?
>>
>>>> Because there should be a honest MI and no interfaces.
>>
>>> But Ada doesn't support honest MI. How do you propose to work-around/
>>> implement that?
>>
>> By changing the language standard, of course. (:-))
>
> Ah, but this brings up a question: HOW do we change it?

1. AI is sent to ARG. 2. ARG accepts AI. 3. ISO receives an amendment. 4.
Springer Verlag prints the text... Or are you asking me how to implement
MI? (:-))

>>> Furthermore, what sort of system would you use to
>>> solve the diamond problem?
>>
>> I don't need to solve it. It is firstly not a problem and secondly it
>> perfectly exists in interfaces:
>>
>> � �type A is interface;
>> � �procedure F (X : A) is abstract;
>> � �type B is interface and A;
>> � �type C is interface and A;
>> � �type D is interface and B and C;
>>
>> It also does in packages (with/use) and many other cases.
>
> But isn't B.F exactly equal to C.F in that we're using an inherited
> procedure/function?

Nope. A is an abstract list node, F is the operation get next node in the
list. B is the list of devices. C is the list processes. Each note
participates in two lists.

> The diamond problem is about components named the
> same that have different types... because interfaces ARE abstract
> objects (with the further restriction that they are denied fields)
> they don't suffer from the diamond problem. {That is the footprint of
> Procedure Foo is EXACTLY the same in all three, they are all the
> same.}

Wrong:

1. There is no whatsoever difference between operations and fields. Each
field is equivalent to a pair of primitive operations (getter and setter).

2. Whether an inheritance is additive or else idempotent depends on the
problem space. It is not the language designer's choice. It is a common
mistake to think otherwise. All misconceptions about MI stem from there.

>>>> You do not need explicitly named contracts in a language like Ada. The
>>>> contract of a type is the type itself.
>>
>>> Agreed, you could define all the operations of both inherited types,
>>> have them as mix-in components, and handle things that way. That
>>> method however excludes the option of saying something like "if Hybrid
>>> in Clothing.Button" and "if hybrid in UI.Button" at the same time (you
>>> could inherit from one and then be able to use one of the above,
>>> true).
>>
>> Use T'Class with membership test S in T'Class.
>
> You're right I forgot the 'Class. But the problem still stands with it
> rewritten as such.

There is no problem, it is up to the programmer to decide about 2. If he
chooses button interface to be additive, as in your case, the compiler
shall support his choice. This is pretty simple to do because in Ada these
conflicts are statically checkable.

Resolving such conflicts is also no big deal. For example, one can rename
operations upon inheritance hiding the conflicting ones.

>> If you have a large system, you never know in advance. The code like above
>> is from a real project. We are probably in a minority who actively deploy
>> Ada 2005 features. We have a lot of interfaces and more we have them, less
>> we enjoy them. He have approximately 20-30% of utterly meaningless cut and
>> pasted code because of lack of MI. As a trivial example consider:
>>
>> � �type Read_File is limited interface;
>> � �procedure Read (File : in out Read_File; ...) is abstract;
>>
>> � �type Write_File is limited interface;
>> � �procedure Write (File : in out Write_File; ...) is abstract;
>>
>> � �type Read_Write_File is limited interface and Read_File and Write_File;
>
> I think it points to a bad design. IMO, I think something like this
> would be in order:
>
> Type Abstract_File is limited interface;
> -- All abstractable file operations go here.
> Function Readable( File : in Abstract_File ) return Boolean is
> Abstract;
> Function Writable( File : in Abstract_File ) return Boolean is
> Abstract;
> Procedure Read ( File : in Abstract_File; Stream :
> Stream_Class'Class ) is Abstract;
> Procedure Write( File : in Abstract_File; Stream :
> Stream_Class'Class ) is Abstract;
> -- And so forth.

1. Since when God-classes became good design?

2. Your design defeats the very advantages of Ada as a statically typed
language. I want Write to be *statically* checked. Otherwise I would use a
dynamically typed language there are plenty of.

>> How consider how would you implement these somewhere at the bottom of a
>> hierarchy of concrete file types. Add there some other inheritance axis
>> like handles to files, different contents, different devices (here you will
>> badly need MD, but that is another story). Then observe how code
>> duplication propagates from the bottom up all the inheritance levels
>> multiplying itself at each. This is customary fought using generics which
>> crown the mess.
>>
>>>> Sure. Translated to OO: FS is a specialized persistent container library.
>>
>>> Excellent. Why then would it be a bad idea to support FS-in-the-
>>> abstract considering that currently [virtually] everyone's data is in
>>> one instance or another of this "specialized persistent container
>>> library"?
>>
>> Surely it is.
>
> That doesn't answer the WHY question.

I don't propose to have no containers.

>>> It would make things easier from the migration-to
>>> standpoint.
>>
>> It would not, because the difference is not in a tree-like structure of
>> named elements, but in the types of those elements.
>
> Um, are you forgetting the librarian/library/book metaphor from
> earlier? The FILE is like the book, it's type is a property of the
> abstract-type "book," the Library is the physical drive where you go
> to get said book, the librarian is the one who knows how to traverse
> the organization/disorganization within the library is the FS. (Not
> all FSes are Hierarchical, think of them as some ADT holding some
> File'Class objects.)

I don't understand how this is related to the question how to handle books.

>>>>>>>> Without MI, MD, tagged tasks, there is no chance to get
>>>>>>>> it right.
>>
>>> Couldn't we emulate tagged tasks [to some degree] by having a "Tag"
>>> entry with an output parameter giving the tag?
>>
>> You have to be able to derive from a task, that is what active objects are.
>> BTW, you already can do this in Ada 2005. It has task interfaces, but this
>> inheritance is limited to have the depth of 1.
>
> I remember reading that now... but is an inheritance level of 1 good
> enough?

No, it is not. The bottom level is an interface, a quite useless thing
because it does not provide implementation. The next level is a concrete
implementation. The train stops there.

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