www.digitalmars.com         C & C++   DMDScript  

D - Feature Proposal (Interface Extensions)

reply "christopher diggins" <cdiggins users.sourceforge.net> writes:
A feature that I find missing in D is the ability to write functions in
interfaces that can call other functions of the interface. Given an
interface ISomeInteface the only way we can write a general purpose function
to operate on all objects which implement that interface is through the
following style of declaration :

    FuBar(ISomeInterface i) { ... };

Which when invoked requires the following syntax :

    FuBar(i);

What would be more keeping with the spirit of object oriented syntax would
be to be able to define interface functions which allow the more
straightforward object-like syntax of :

    i.FuBar();

For lack of a better term I refer to these kinds of functions as interface
extensions, in order to distinguish them from interface contract (the set of
functions to be implemented, by an implementor of the interface). One
possible approach for adding this feature is to prefix extension functions
with a keyword modifier, such as in the following notation :

    SomeInterface {
        extension FuBar() { ... }
    }

Another possibility, and my preferred option, is to divide the interface
into two sections :

    SomeInterface {
        contract
            ...
        extension
            FuBar();
    }

For those interested there is a draft of a paper on this feature as it is
proposed in Heron at http://www.heron-language.com/extensions.html . I would
like to know what others think of this proposal. Thanks in advance for your
feedback.

-- 
Christopher Diggins
yet another language designer
http://www.heron-language.com
Feb 04 2004
next sibling parent reply Georg Wrede <Georg_member pathlink.com> writes:
In article <bvreas$23u9$1 digitaldaemon.com>, christopher diggins says...
A feature that I find missing in D is the ability to write functions in
interfaces that can call other functions of the interface. Given an
interface ISomeInteface the only way we can write a general purpose 
function to operate on all objects which implement that interface is 

.. The following page has an interesting discussion about the issue: http://www.heron-language.com/extensions.html " Interfaces with extensions and a mechanism for delegating implementation to member fields can replace entirely class inheritance as a means for providing polymorphic objects. Such a system would have advantages in that it supports yet clearly distinguishes between inheritance of a role (interface) and inheritance of implementation. " While this does sound, er, unbelievable, to me, if there's half a truth in this, then this could mean that the major part of OO code existing today could be rewritten. (This does not necessarily bear a precedent, but this reminds me of C++ and multiple inheritance.) MI was one of the most ferrociously advocated features in C++ in the late '80s. Only afterwards it became clear that there was actually (almost) no use for the feature. Multiple paths from the same ancestor class screwed up the issue. (Not to mention it was one hell for bigW and others who actually had to conjure up the stuff!) Until someone (sorry, I forget who) demostrated that all you have to do is to have the interface multiply inherited, then you don't have to MI any implementation -- as a matter of fact, you really _shouldn't_. If the interface definition would allow us to have functions call each other, then it would be easy to convey in the ID that you may have only a very few functions that actually do any manipulation of the attributes. This could lead to code that is less dependent on details, and code that is easier to maintain. If the internal definitions of attributes change, then this way only the _very_ few functions that actually manipulate the attributes would have to change. The other interface functions (could be considered clients of these, and therefore) would not need any modifications. While I wouldn't even dream of skipping D for Heron, I have to admit that there are quite some things Heron seems to do right! Separate operators for value and reference assignment is the absolutely most brilliant idea I have ever seen in a language. And there are others.
Feb 04 2004
parent reply "christopher diggins" <cdiggins users.sourceforge.net> writes:
"Georg Wrede" <Georg_member pathlink.com> wrote in message
news:bvrvdm$30or$1 digitaldaemon.com...
 In article <bvreas$23u9$1 digitaldaemon.com>, christopher diggins says...
A feature that I find missing in D is the ability to write functions in
interfaces that can call other functions of the interface. Given an
interface ISomeInteface the only way we can write a general purpose
function to operate on all objects which implement that interface is

.. The following page has an interesting discussion about the issue: http://www.heron-language.com/extensions.html " Interfaces with extensions and a mechanism for delegating implementation to member fields can replace entirely class inheritance as a means for providing polymorphic objects. Such a system would have advantages in that it supports yet clearly distinguishes between inheritance of a role (interface) and inheritance of implementation. " While this does sound, er, unbelievable, to me, if there's half a truth in this, then this could mean that the major part of OO code existing today could be rewritten.

Well I am reasonably confident that what I propose is wholly true, I don't see rewriting existing OO code as a goal. Just perhaps that people would abandon the misuse of virtual functions.
 (This does not necessarily bear a precedent, but this reminds me
 of C++ and multiple inheritance.) MI was one of the most
 ferrociously advocated features in C++ in the late '80s. Only
 afterwards it became clear that there was actually (almost) no
 use for the feature. Multiple paths from the same ancestor class
 screwed up the issue. (Not to mention it was one hell for bigW
 and others who actually had to conjure up the stuff!)

 Until someone (sorry, I forget who) demostrated that all you have
 to do is to have the interface multiply inherited, then you don't
 have to MI any implementation -- as a matter of fact, you really
 _shouldn't_.

 If the interface definition would allow us to have functions call
 each other, then it would be easy to convey in the ID that you
 may have only a very few functions that actually do any manipulation
 of the attributes. This could lead to code that is less dependent
 on details, and code that is easier to maintain. If the internal
 definitions of attributes change, then this way only the _very_
 few functions that actually manipulate the attributes would have
 to change. The other interface functions (could be considered
 clients of these, and therefore) would not need any modifications.

I am glad you see this the same way that I do. This was exactly the design intention when I introduced it into Heron. So perhaps we should petition Walter together to consider including it in D?
 While I wouldn't even dream of skipping D for Heron, I have to
 admit that there are quite some things Heron seems to do right!

 Separate operators for value and reference assignment is the
 absolutely most brilliant idea I have ever seen in a language.
 And there are others.

Very kind words, Georg, thank you. -- Christopher Diggins yet another language designer http://www.heron-language.com
Feb 04 2004
parent reply Georg Wrede <Georg_member pathlink.com> writes:
Author: "christopher diggins" <cdiggins users.sourceforge.net>
 
 I am glad you see this the same way that I do. This was exactly
 the design intention when I introduced it into Heron. So perhaps
 we should petition Walter together to consider including it in D?

D does not separate declaration from definition, so there might not even be any need for new keywords (such as contract or extension). Anybody could see right away that some of the methods have bodies, and since this is an interface, they must be Extensions. OTOH, it might be clearer for the reader (and writer himself) if the words contract and extension were there. (But if you don't use extensions, then neither word has to be there.) What do you think is the minimum set of rules the compiler would have to have, if we were to implement extensions?
Feb 05 2004
parent reply "christopher diggins" <cdiggins users.sourceforge.net> writes:
"Georg Wrede" <Georg_member pathlink.com> wrote in message
news:bvu8lv$nt0$1 digitaldaemon.com...
 Author: "christopher diggins" <cdiggins users.sourceforge.net>
 I am glad you see this the same way that I do. This was exactly
 the design intention when I introduced it into Heron. So perhaps
 we should petition Walter together to consider including it in D?

D does not separate declaration from definition, so there might not even be any need for new keywords (such as contract or extension). Anybody could see right away that some of the methods have bodies, and since this is an interface, they must be Extensions. OTOH, it might be clearer for the reader (and writer himself) if the words contract and extension were there. (But if you don't use extensions, then neither word has to be there.)

I do think it would be clearer to at the very minimum identify extension functions, so that users don't think they are supposed to provide an implementation for that function.
 What do you think is the minimum set of rules the compiler
 would have to have, if we were to implement extensions?

Well to cause the least syntactic disruption, we could introduce it as follows : interface IFuBar { void RegularIntefaceFxn(); extension void ExtensionFxn() { RegularInterfaceFxn() }; } The compiler could automatically generate the function for any class implementing IFuBar exactly as it appears. I don't know how naming conflicts are dealt with in the D compiler, but the same solution that is used to resolve naming conflicts between multiple interfaces within a class could likely be used. Am I on the right track? By the way Georg I tried sending you a private email to participate in discussions on Heron, but it bounced back. May I write you privately? You can email me at cdiggins users.sourceforge.net to give me another address I can use. Thanks -- Christopher Diggins yet another language designer http://www.heron-language.com
Feb 05 2004
next sibling parent reply Georg Wrede <Georg_member pathlink.com> writes:
In article <bvu9ql$psb$1 digitaldaemon.com>, christopher diggins says...
 What do you think is the minimum set of rules the compiler
 would have to have, if we were to implement extensions?

Well to cause the least syntactic disruption, we could introduce it as follows : interface IFuBar { void RegularIntefaceFxn(); extension void ExtensionFxn() { RegularInterfaceFxn() }; }

This seems quite reasonable.
The compiler could automatically generate the function for any class
implementing IFuBar exactly as it appears. 

Yes, this would save typing, and prevent unnecessary bugs in user code. And of course, the child class may freely reimplement any or all of them if need be.
I don't know how naming conflicts
are dealt with in the D compiler, but the same solution that is used to
resolve naming conflicts between multiple interfaces within a class could
likely be used. 

Good point.
Am I on the right track?

I was thinking more like the dos and don'ts of extensions. Since you've obviously used this tehnique for some time, you may have ideas on what the programmer could be allowed to write in an extension function. The interface function can't do anything, it's supposed to be totally implemented by the inheriting class. In the same way, the extension function can't assume things about the internals of the inheriting class. And to enforce this, I thought the compiler could error such code. Also, I wouldn't be surprised if it were wise to further limit this code somehow -- but right now this is just a gut feeling.
Feb 06 2004
parent reply "christopher diggins" <cdiggins users.sourceforge.net> writes:
"Georg Wrede" <Georg_member pathlink.com> wrote in message
news:bvvmcl$c3$1 digitaldaemon.com...
 In article <bvu9ql$psb$1 digitaldaemon.com>, christopher diggins says...
 What do you think is the minimum set of rules the compiler
 would have to have, if we were to implement extensions?

Well to cause the least syntactic disruption, we could introduce it as follows : interface IFuBar { void RegularIntefaceFxn(); extension void ExtensionFxn() { RegularInterfaceFxn() }; }

This seems quite reasonable.
The compiler could automatically generate the function for any class
implementing IFuBar exactly as it appears.

Yes, this would save typing, and prevent unnecessary bugs in user code. And of course, the child class may freely reimplement any or all of them if need be.

That would lead to a naming conflict, which I suppose we could resolve by having the class itself hide any extension implementation. A problem arises within an extension function A when it calls another extension function B which is reimplemented by the class as function C. Does A call B or C? In Heron I currently specify that A calls B. Perhaps it is more intuitive to most that A calls C.
I don't know how naming conflicts
are dealt with in the D compiler, but the same solution that is used to
resolve naming conflicts between multiple interfaces within a class could
likely be used.

Good point.
Am I on the right track?

I was thinking more like the dos and don'ts of extensions. Since you've obviously used this tehnique for some time, you may have ideas on what the programmer could be allowed to write in an extension function. The interface function can't do anything, it's supposed to be totally implemented by the inheriting class. In the same way, the extension function can't assume things about the internals of the inheriting class. And to enforce this, I thought the compiler could error such code. Also, I wouldn't be surprised if it were wise to further limit this code somehow -- but right now this is just a gut feeling.

Oh I see, so we need to explicitly say to the compiler what it can see. It can't call any functions except those of the interface (and any sub-interfaces) and it can't access any fields. It can access anything in the At this point though I think I should stop posting on this topic since no one else, other than Georg, seems to be interested. I made similar feature proposals on the Java and C# newsgroups, and the interest in it was virtually nil. Most of the topics are along the lines of "this is too much like MI therefore it is bad". I guess not many people are able to (or perhaps don't want to?) see the advantage of this feature. Spending further energy working out how to incorporate the feature in D seems pointless if Walter isn't interested. -- Christopher Diggins yet another language designer http://www.heron-language.com
Feb 06 2004
parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
<snip>

 At this point though I think I should stop posting on this topic since no
 one else, other than Georg, seems to be interested. I made similar feature
 proposals on the Java and C# newsgroups, and the interest in it was
 virtually nil. Most of the topics are along the lines of "this is too much
 like MI therefore it is bad". I guess not many people are able to (or
 perhaps don't want to?) see the advantage of this feature.

I want to see the point, but I just don't. I think you need to provide us with a clear and compelling (by which I mean non-trival, "real") example. I understand the mechanism, and have used the technique here and there in C/COM/C++, but I just don't get the "higher" significance that your propounding. Don't get me wrong: I'm open to the idea that you're onto something significant, and I want to see it. I just don't, yet. Please pursue it.
 Spending further
 energy working out how to incorporate the feature in D seems pointless if
 Walter isn't interested.

This NG doesn't work by attracting any response from Walter on most issues for quite a while. You'll need to get it past the shit-filters - that's all of us - before he'll even notice it; he's a busy man. ;)
Feb 06 2004
prev sibling parent reply Andy Friesen <andy ikagames.com> writes:
christopher diggins wrote:
 
 Well to cause the least syntactic disruption, we could introduce it as
 follows :
 
 interface IFuBar {
     void RegularIntefaceFxn();
     extension void ExtensionFxn() { RegularInterfaceFxn() };
 }
 

Nearly every abstract class I write follows this pattern. It's a good idiom. Is the 'extension' keyword really needed? It's unambigious as far as I can tell: methods that are defined are extensions, methods that are not are part of the contract. This is kind of interesting in that it nearly unifies classes and interfaces. The latter is merely forbidden from containing attributes or extending classes. -- andy
Feb 06 2004
parent "christopher diggins" <cdiggins users.sourceforge.net> writes:
"Andy Friesen" <andy ikagames.com> wrote in message
news:c00glo$1bfc$1 digitaldaemon.com...
 christopher diggins wrote:
 Well to cause the least syntactic disruption, we could introduce it as
 follows :

 interface IFuBar {
     void RegularIntefaceFxn();
     extension void ExtensionFxn() { RegularInterfaceFxn() };
 }

Nearly every abstract class I write follows this pattern. It's a good idiom. Is the 'extension' keyword really needed? It's unambigious as far as I can tell: methods that are defined are extensions, methods that are not are part of the contract.

Well it depends on whether we actually allow the extension to be implemented by the class as an override or hidden, or a naming conflict that must be explicitly resolved.
 This is kind of interesting in that it nearly unifies classes and
 interfaces.  The latter is merely forbidden from containing attributes
 or extending classes.

This identifies part of the reason for the extension. With one other mechanism (interface implementation delegation to member fields), we could create object oriented designs without class inheritance. Part of my premise is that class inheritance as is commonly implemented, is an inherently flawed mechanism. -- Christopher Diggins yet another language designer http://www.heron-language.com
Feb 06 2004
prev sibling next sibling parent reply "Ben Hinkle" <bhinkle4 juno.com> writes:
Interesting proposal - allow multiple inheritance of classes without fields.
If the implementations of any inherited method are all the same then it
would be ok, I suppose. This is unlike inheriting multiple copies of a field
since the name becomes ambiguous. I've grown used to the mantra "classes
have code/data and interfaces don't" so the lack of this feature in D
doesn't bother me.

On a side note, I read in the D doc that it is illegal to inherit duplicate
interfaces:

interface D
	{
	    void foo();
	}
	class A : D, D	// error, duplicate interface
	{
	}

But is this legal:

interface D
{
    void foo();
}
interface D2 : D
{
}
class A : D, D2
{
}

Why rule out duplicate interfaces when you can just create an empty
sub-interface? If the first breaks some compiler logic one would think the
second one would, too.

-Ben

"christopher diggins" <cdiggins users.sourceforge.net> wrote in message
news:bvreas$23u9$1 digitaldaemon.com...
| A feature that I find missing in D is the ability to write functions in
| interfaces that can call other functions of the interface. Given an
| interface ISomeInteface the only way we can write a general purpose
function
| to operate on all objects which implement that interface is through the
| following style of declaration :
|
|     FuBar(ISomeInterface i) { ... };
|
| Which when invoked requires the following syntax :
|
|     FuBar(i);
|
| What would be more keeping with the spirit of object oriented syntax would
| be to be able to define interface functions which allow the more
| straightforward object-like syntax of :
|
|     i.FuBar();
|
| For lack of a better term I refer to these kinds of functions as interface
| extensions, in order to distinguish them from interface contract (the set
of
| functions to be implemented, by an implementor of the interface). One
| possible approach for adding this feature is to prefix extension functions
| with a keyword modifier, such as in the following notation :
|
|     SomeInterface {
|         extension FuBar() { ... }
|     }
|
| Another possibility, and my preferred option, is to divide the interface
| into two sections :
|
|     SomeInterface {
|         contract
|             ...
|         extension
|             FuBar();
|     }
|
| For those interested there is a draft of a paper on this feature as it is
| proposed in Heron at http://www.heron-language.com/extensions.html . I
would
| like to know what others think of this proposal. Thanks in advance for
your
| feedback.
|
| --
| Christopher Diggins
| yet another language designer
| http://www.heron-language.com
|
|
Feb 04 2004
next sibling parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Ben Hinkle" <bhinkle4 juno.com> wrote in message
news:bvrvvn$31iu$1 digitaldaemon.com...
 Interesting proposal - allow multiple inheritance of classes without

 If the implementations of any inherited method are all the same then it
 would be ok, I suppose. This is unlike inheriting multiple copies of a

 since the name becomes ambiguous. I've grown used to the mantra "classes
 have code/data and interfaces don't" so the lack of this feature in D
 doesn't bother me.

 On a side note, I read in the D doc that it is illegal to inherit

 interfaces:

 interface D
 {
     void foo();
 }
 class A : D, D // error, duplicate interface
 {
 }

This is entirely meaningless. There's no difference between class A : D {} and class A : D, D, D, D, D, D, ... , D {}, because all you can do with A is deduce that it is of type A or of type D.
 But is this legal:

 interface D
 {
     void foo();
 }
 interface D2 : D
 {
 }
 class A : D, D2
 {
 }

I didn't know D allowed this. If it does, I think it shouldn't. C++ does not. Something like the following is legal interface D{}; interface D1 : D {}; interface D2 : D {}; class A : D1, D2 {}; This is useful. If D1 and/or D2 provide additional functionality, then the benefit is obvious. However, even if they provide no additional functionality it can still be useful, in the same way that COM uses empty "tag" interfaces. Of course, I hate RTTI with a grand passion, so I'm being somewhat hypocritical here, but you can see that there is technical merit in the ability to deduce whether A is of type D1 and/or D2.
 Why rule out duplicate interfaces when you can just create an empty
 sub-interface? If the first breaks some compiler logic one would think the
 second one would, too.

 -Ben

 "christopher diggins" <cdiggins users.sourceforge.net> wrote in message
 news:bvreas$23u9$1 digitaldaemon.com...
 | A feature that I find missing in D is the ability to write functions in
 | interfaces that can call other functions of the interface. Given an
 | interface ISomeInteface the only way we can write a general purpose
 function
 | to operate on all objects which implement that interface is through the
 | following style of declaration :
 |
 |     FuBar(ISomeInterface i) { ... };
 |
 | Which when invoked requires the following syntax :
 |
 |     FuBar(i);
 |
 | What would be more keeping with the spirit of object oriented syntax

 | be to be able to define interface functions which allow the more
 | straightforward object-like syntax of :
 |
 |     i.FuBar();
 |
 | For lack of a better term I refer to these kinds of functions as

 | extensions, in order to distinguish them from interface contract (the

 of
 | functions to be implemented, by an implementor of the interface). One
 | possible approach for adding this feature is to prefix extension

 | with a keyword modifier, such as in the following notation :
 |
 |     SomeInterface {
 |         extension FuBar() { ... }
 |     }
 |
 | Another possibility, and my preferred option, is to divide the interface
 | into two sections :
 |
 |     SomeInterface {
 |         contract
 |             ...
 |         extension
 |             FuBar();
 |     }
 |
 | For those interested there is a draft of a paper on this feature as it

 | proposed in Heron at http://www.heron-language.com/extensions.html . I
 would
 | like to know what others think of this proposal. Thanks in advance for
 your
 | feedback.
 |
 | --
 | Christopher Diggins
 | yet another language designer
 | http://www.heron-language.com
 |
 |

Feb 04 2004
prev sibling parent Antti =?iso-8859-1?Q?Syk=E4ri?= <jsykari gamma.hut.fi> writes:
In article <bvrvvn$31iu$1 digitaldaemon.com>, Ben Hinkle wrote:
 Interesting proposal - allow multiple inheritance of classes without fields.

If this is what was proposed in the original post, I'm all for it. (I couldn't quite understand what was actually suggested, but then again I'm tired and all that)
 On a side note, I read in the D doc that it is illegal to inherit duplicate
 interfaces:
 
 interface D
 	{
 	    void foo();
 	}
 	class A : D, D	// error, duplicate interface
 	{
 	}
 
 But is this legal:
 
 interface D
 {
     void foo();
 }
 interface D2 : D
 {
 }
 class A : D, D2
 {
 }
 
 Why rule out duplicate interfaces when you can just create an empty
 sub-interface? If the first breaks some compiler logic one would think the
 second one would, too.

I'd prefer that the note in the D docs about multiple interfaces would be removed. Why explicitly ban a "feature" that does nothing? It's ok for me to still flag it as an error, because nobody will probably ever do it because it's, well, of no use (As Matthew, I think, pointed out.) -Antti
Feb 22 2004
prev sibling parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
Hi Christopher.

I read the paper, and this post, carefully, but I'm let down my a kinetic
mind. I need to see real examples, otherwise it's all just fuzz to me.

If you have the time, I'd very much appreciate your providing a fleshed out
example to demonstrate what you mean, and from which I can make a reasoned
assessment of your idea.

Cheers

Matthew


"christopher diggins" <cdiggins users.sourceforge.net> wrote in message
news:bvreas$23u9$1 digitaldaemon.com...
 A feature that I find missing in D is the ability to write functions in
 interfaces that can call other functions of the interface. Given an
 interface ISomeInteface the only way we can write a general purpose

 to operate on all objects which implement that interface is through the
 following style of declaration :

     FuBar(ISomeInterface i) { ... };

 Which when invoked requires the following syntax :

     FuBar(i);

 What would be more keeping with the spirit of object oriented syntax would
 be to be able to define interface functions which allow the more
 straightforward object-like syntax of :

     i.FuBar();

 For lack of a better term I refer to these kinds of functions as interface
 extensions, in order to distinguish them from interface contract (the set

 functions to be implemented, by an implementor of the interface). One
 possible approach for adding this feature is to prefix extension functions
 with a keyword modifier, such as in the following notation :

     SomeInterface {
         extension FuBar() { ... }
     }

 Another possibility, and my preferred option, is to divide the interface
 into two sections :

     SomeInterface {
         contract
             ...
         extension
             FuBar();
     }

 For those interested there is a draft of a paper on this feature as it is
 proposed in Heron at http://www.heron-language.com/extensions.html . I

 like to know what others think of this proposal. Thanks in advance for

 feedback.

 -- 
 Christopher Diggins
 yet another language designer
 http://www.heron-language.com

Feb 04 2004
parent "christopher diggins" <cdiggins users.sourceforge.net> writes:
"Matthew" <matthew.hat stlsoft.dot.org> wrote in message
news:bvs44p$6da$1 digitaldaemon.com...
 Hi Christopher.

 I read the paper, and this post, carefully, but I'm let down my a kinetic
 mind. I need to see real examples, otherwise it's all just fuzz to me.

 If you have the time, I'd very much appreciate your providing a fleshed

 example to demonstrate what you mean, and from which I can make a reasoned
 assessment of your idea.

 Cheers

 Matthew

Hi Matthew, There is an example in the paper involving Binary Search Trees. The first part of the example is an interface for an ITreeNode which demonstrates how four functions make up the contract : GetValue, GetLeftChild, GetRightChild, GetParent. We then can deduce four functions :GetMinimum, GetMaximum, GetSuccessor, GetPredecessor; as an extension. Those are functions that essentially come for free for any class that implements the contracts of the extension. What is troublesome for you with this example? If I may try to simplify it, the concept is that for certain interfaces there are many functions which can be defined in terms of other functions of that particular interface. This is an extension. To bring in a perhaps less abstract example : interface IString { contract GetNumChars() : int; GetChar(int i) : char; SetNumChars(int n); SetChar(int i, char c); extension Append(IString& s); ConvertToUppercase(); ConvertToLowercase(); ReverseStr(); SetAllCharsTo(char c); Clear(); ... } The extension are all the functions that you can imagine defining from the first part. How am I doing? -- Christopher Diggins yet another language designer http://www.heron-language.com
Feb 04 2004