Thread overview
How to 'add' functions to existing type/class/struct/interface...
May 19, 2011
Matthew Ong
May 19, 2011
Adam D. Ruppe
May 21, 2011
Matthew Ong
May 21, 2011
Matthew Ong
May 19, 2011
Hi All/Walter Bright,

The ability is able to be model and done by JRuby and also Google Go.


Conversions
...
// this function is now available for the object type Sequence. Done outside of Sequence.d
func (s Sequence) MyFunction() string {
   //  My Function has access to all the public/internal data of the
   // Sequence here.
}
...
s Sequence;
s.MyFunction(); // now that can be used. Completelty new Function outside of Sequence.d

That is some how like JRuby ability to 'add' method into the java final String class without really touching that class String.

Interfaces and methods

Since almost anything can have methods attached, almost anything can satisfy an
interface. One illustrative example is in the http package, which defines the
Handler interface. Any object that implements Handler can serve HTTP requests.

It is not just entirely like java interfaces, but java has to somehow, code the api in a very strange pattern to support this.

I read from Adam that it is possible and is done within Phobos by D.
Could some one provide some sample code to explain that.

Mixin and Template does not quite fit there I think, in other language(Java/C#) are more for code reusing rather than code 'injection'.

Perhaps that is not the case within D as a limitation. Some code example would be really useful.



-- 
Matthew Ong
email: ongbp@yahoo.com

May 19, 2011
> How to 'add' functions to existing type/class/struct/interface...

You don't. It seems to be that this would break encapsulation anyway.

> I read from Adam that it is possible and is done within Phobos by D. Could some one provide some sample code to explain that.

Look in std.range for full examples but here's a brief one:

void doSomething(T)(T item) if( isMyInterface!T ) {
     // use item here
}

template isMyInterface(T) {
     static if(is(typeof(
           // write some code to test the interface here
     )))
         enum bool isMyInterface = true;
     else
         enum bool isMyInterface = false;
}



You can also use the template straight up, though that's less structured:

auto doSomething(T)(T obj) {
     // write whatever you want here using obj
     // it won't compile if the obj doesn't match the used functions
}



Or, you can go with a more strictly Go style by using method #1 and automating the isMyInterface detection. Kenju Hara wrote an adaptTo function that does something like this:

interface Interface {
    void foo();
}


class A { // note it doesn't list the interface here
     void foo();
}

void func(Interface i) { }


A a = new A();

func(adaptTo!Interface(a));


I don't think this has been committed to Phobos yet though.
May 21, 2011
On 5/19/2011 11:23 PM, Adam D. Ruppe wrote:
>> How to 'add' functions to existing type/class/struct/interface...
>
> You don't. It seems to be that this would break encapsulation anyway.
This block of comments is totally not related to this thread, but just to set the record straight.

Not entirely. Only data that you deem safe are expose. Go does not have public/private keyword, but they uses first letter of the Identifier of Functions or Variables to define encapsulation(strange+implied).

Uppercase first letter = Public.
lowercase first letter = Private.


>> I read from Adam that it is possible and is done within Phobos by D.
>> Could some one provide some sample code to explain that.
>
> Look in std.range for full examples but here's a brief one:
Ok. Thanks.
> void doSomething(T)(T item) if( isMyInterface!T ) {
>       // use item here
> }
> template isMyInterface(T) {
>       static if(is(typeof(
>             // write some code to test the interface here
     ... Do not know what is done here because I am new.
>       )))
>           enum bool isMyInterface = true;
>       else
>           enum bool isMyInterface = false;
> }
Because I am new to D, That is a very strange syntax to me. I suppose the std.range example may give more clarity.

>
> You can also use the template straight up, though that's less
> structured:
>
> auto doSomething(T)(T obj) {
>       // write whatever you want here using obj
>       // it won't compile if the obj doesn't match the used functions
> }
This example is more like a static generics in Java for me. But it is a form of the polymorphic ability. It does not add

> Or, you can go with a more strictly Go style by using method #1
> and automating the isMyInterface detection. Kenju Hara wrote
> an adaptTo function that does something like this:
>
> interface Interface {
>      void foo();
> }
>
>
> class A { // note it doesn't list the interface here
>       void foo();
> }
>
> void func(Interface i) { }
>
>
> A a = new A();
>
> func(adaptTo!Interface(a));
>
>
> I don't think this has been committed to Phobos yet though.
This last example fits the Go interfaces example the best. I think, but there is no code for adaptTo(T). There is no clear idea how this is done.

From what I can see Go is doing is like in C/C++:
1) using structure to define the data-type. // Class Object is more expensive.
2) static functions that bind to that structure datatype. Such static functions can be define within the LIB or introduced as new functions outside the library.
3) using some form of function pointer to call those static functions.

-- 
Matthew Ong
email: ongbp@yahoo.com

May 21, 2011
On 5/19/2011 11:23 PM, Adam D. Ruppe wrote:
>> How to 'add' functions to existing type/class/struct/interface...
>
> You don't. It seems to be that this would break encapsulation anyway.
Not entirely. As seen within JRuby and Go.
JRuby shown that the methods defined within java.lang.String are not corrupted and the new functions can also be entirely independent to String. But that is done with a lot of runtime plumbing within the JRuby
engine. I think they injected some bytecode using BSH to do that without touching the String.class file in JVM. Hence, I suspected it has nothing to do with breaking a library's encapsulation.

Not too sure about Go as it was designed from ground up to do this.

This block of comments is totally not related to this thread, but just to set the record straight.
----------------------------------------------------------------------
Only data that you deem safe are expose. Go does not have public/private keyword, but they uses first letter of the Identifier of Functions or Variables to define encapsulation(strange+implied).

Uppercase first letter = Public.
lowercase first letter = Private.
----------------------------------------------------------------------

>> I read from Adam that it is possible and is done within Phobos by D.
>> Could some one provide some sample code to explain that.
>
> Look in std.range for full examples but here's a brief one:
Ok. Thanks.
> void doSomething(T)(T item) if( isMyInterface!T ) {
>       // use item here
> }
> template isMyInterface(T) {
>       static if(is(typeof(
>             // write some code to test the interface here
     ... Do not know what is done here because I am new...
>       )))
>           enum bool isMyInterface = true;
>       else
>           enum bool isMyInterface = false;
> }
Because I am new to D, That is a very strange syntax to me. I suppose the std.range example may give more clarity.

>
> You can also use the template straight up, though that's less
> structured:
>
> auto doSomething(T)(T obj) {
>       // write whatever you want here using obj
>       // it won't compile if the obj doesn't match the used functions
> }
This example is more like a static generics in Java for me. But it is a form of the polymorphic ability. It does not add

> Or, you can go with a more strictly Go style by using method #1
> and automating the isMyInterface detection. Kenju Hara wrote
> an adaptTo function that does something like this:
>
> interface Interface {
>      void foo();
> }
>
>
> class A { // note it doesn't list the interface here
>       void foo();
> }
>
> void func(Interface i) { }
>
>
> A a = new A();
>
> func(adaptTo!Interface(a));
>
>
> I don't think this has been committed to Phobos yet though.
This last example fits the Go interfaces example the best. I think, but there is no code for adaptTo(T). There is no clear idea how this is done.

From what I can see Go is doing is like in C/C++:
1) using structure to define the data-type. // Class Object is more expensive.
2) static functions that bind to that structure datatype. Such static functions can be define within the LIB or introduced as new functions outside the library.
3) using some form of function pointer to call those static functions.

Hey Adam, you are one of the most experience D person that does give solid answer to experience developers from other language.


Thanks for the answer clarifying this.
-- 
Matthew Ong
email: ongbp@yahoo.com