www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - LazyInterface (simplified Boost.Interfaces)

reply kenji hara <k.hara.pg gmail.com> writes:
Hi.

I heard Boost.Interfaces recently. Then, it implemented by D.
http://github.com/9rnsr/scrap/blob/master/interfaces/interfaces.d

How about you?
Sep 21 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
kenji hara:

 I heard Boost.Interfaces recently. Then, it implemented by D.
 http://github.com/9rnsr/scrap/blob/master/interfaces/interfaces.d
 How about you?
// static auto opDispatch(string Name, Args...)(Args args) // { // enum stc = 's'; // mixin(dispatch); // } } But static opDispatch works: struct Foo { static void opDispatch(string name, Args...)(Args args) { static assert(name == "hello"); } } void main() { Foo.hello(10, 20); } So if you have found a bug you may add a minimized case in Bugzilla. Bye, bearophile
Sep 21 2010
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
There is no problem if it is only static opDispatch or non-static one.
But D does not allow to override theirs together.

We cannot compile this:
class A{
    int f(){return 10;}
    static int f(){return 20;}
}
void main(){
	auto a = new A();
	assert(a.f() == 10);
	assert(A.f() == 20);
}

Thanks.

bearophile wrote:
 But static opDispatch works:

 struct Foo {
    static void opDispatch(string name, Args...)(Args args) {
        static assert(name == "hello");
    }
 }
 void main() {
    Foo.hello(10, 20);
 }


 So if you have found a bug you may add a minimized case in Bugzilla.
Sep 21 2010
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/21/10 14:36 CDT, kenji hara wrote:
 Hi.

 I heard Boost.Interfaces recently. Then, it implemented by D.
 http://github.com/9rnsr/scrap/blob/master/interfaces/interfaces.d

 How about you?
Hi Kenji, Looking very interesting. One thing I'd change would be the interface definition. Ideally the client code would look like this: static class A { int draw(){ return 10; } } static class B : A { int draw(){ return 20; } } interface Drawable { int draw(); }; unittest { Drawable d = adaptTo!Drawable(new A); assert(d.draw() == 10); d = adaptTo!Drawable(new B); assert(d.draw() == 20); } adaptTo would rely on introspection and code generation to define an implementation of Drawable that forwards calls to an object. Andrei
Sep 22 2010
next sibling parent kenji hara <k.hara.pg gmail.com> writes:
Thanks for your advise, Andrei.

I will try to implement adaptTo!T .

Kenji Hara

2010/9/22 Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:
 On 9/21/10 14:36 CDT, kenji hara wrote:
 Hi.

 I heard Boost.Interfaces recently. Then, it implemented by D.
 http://github.com/9rnsr/scrap/blob/master/interfaces/interfaces.d

 How about you?
Hi Kenji, Looking very interesting. One thing I'd change would be the interface definition. Ideally the client code would look like this: static class A { =A0int draw(){ return 10; } } static class B : A { =A0int draw(){ return 20; } } interface Drawable { =A0int draw(); }; unittest { =A0Drawable d =3D adaptTo!Drawable(new A); =A0assert(d.draw() =3D=3D 10); =A0d =3D adaptTo!Drawable(new B); =A0assert(d.draw() =3D=3D 20); } adaptTo would rely on introspection and code generation to define an implementation of Drawable that forwards calls to an object. Andrei
Sep 22 2010
prev sibling parent reply kenji hara <k.hara.pg gmail.com> writes:
I implemented adaptTo .

http://github.com/9rnsr/scrap/blob/master/interfaces/interfaces.d

Kenji Hara

2010/9/22 kenji hara <k.hara.pg gmail.com>:
 Thanks for your advise, Andrei.

 I will try to implement adaptTo!T .

 Kenji Hara

 2010/9/22 Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:
 On 9/21/10 14:36 CDT, kenji hara wrote:
 Hi.

 I heard Boost.Interfaces recently. Then, it implemented by D.
 http://github.com/9rnsr/scrap/blob/master/interfaces/interfaces.d

 How about you?
Hi Kenji, Looking very interesting. One thing I'd change would be the interface definition. Ideally the client code would look like this: static class A { =A0int draw(){ return 10; } } static class B : A { =A0int draw(){ return 20; } } interface Drawable { =A0int draw(); }; unittest { =A0Drawable d =3D adaptTo!Drawable(new A); =A0assert(d.draw() =3D=3D 10); =A0d =3D adaptTo!Drawable(new B); =A0assert(d.draw() =3D=3D 20); } adaptTo would rely on introspection and code generation to define an implementation of Drawable that forwards calls to an object. Andrei
Sep 23 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/23/10 8:09 CDT, kenji hara wrote:
 I implemented adaptTo .

 http://github.com/9rnsr/scrap/blob/master/interfaces/interfaces.d

 Kenji Hara
This is great work, Kenji! I'm very glad about this because it uses introspection to implement an important feature. Such post-hoc interface binding is a core feature in quite a few languages. If you agree, I am committed to advocate adopting this abstraction for Phobos in module std.typecons, with credit. All - a bit of bikeshedding - what is a better name for adaptTo? I know there is a consecrated name for such late matching of an interface, but I can't remember it. A few nits about the implementation: * In line 73 it looks like you don't support covariance of return types. Could you fix that? Example (add it to the unittests, too): class C { long draw(){ return 10; } } interface Drawable { int draw(); } The override should be legit. * Throughout: everything that is a value should start with a lowercase letter; everything that is not a value (e.g. type, type tuple) should start with an uppercase letter. In particular your "result" convention should use "Result" for type results and "result" for value results. * Code shouldn't use uppercase "i" as a symbol name - it's confusable with "1". Congratulations! This is great work indeed. Thanks, Andrei
Sep 23 2010
next sibling parent kenji hara <k.hara.pg gmail.com> writes:
Thanks very much!

 If you agree, I am committed to advocate adopting this abstraction for Phobos
in module std.typecons, with credit.
Of couse, I agree.
 All - a bit of bikeshedding - what is a better name for adaptTo? I know there
is a consecrated name for such late matching of an interface, but I can't
remember it.
from here(http://www.coderage.com/interfaces/), I found two keywords. - Non-intrusive dynamic polymorphism - Aspect Oriented Programming How about you? I understood the covariance problem. I think that I should also support it. By the way, there is a question about this sample code.
 class C
 {
  long draw(){ return 10; }
 }
 interface Drawable
 {
  int draw();
 }
In my opinion, C can derive from Drawable ideally. so, it will be satisfied with this code. static assert(isCovariantWith!(typeof(C.draw), typeof(Drawable.draw))); Correctness of it is like this, isn't it? class C { int draw(){ return 10; } } interface Drawable { long draw(); }
 The override should be legit.
I will fix them. Kenji Hara
Sep 23 2010
prev sibling parent reply kenji hara <k.hara.pg gmail.com> writes:
I supported covariance of return types.
Please check it.

2010/9/24 kenji hara <k.hara.pg gmail.com>:
 Thanks very much!

 If you agree, I am committed to advocate adopting this abstraction for P=
hobos in module std.typecons, with credit.
 Of couse, I agree.


 All - a bit of bikeshedding - what is a better name for adaptTo? I know =
there is a consecrated name for such late matching of an interface, but I c= an't remember it.
 from here(http://www.coderage.com/interfaces/), I found two keywords.
 - Non-intrusive dynamic polymorphism
 - Aspect Oriented Programming
 How about you?


 I understood the covariance problem. I think that I should also support i=
t.
 By the way, there is a question about this sample code.
 class C
 {
 =A0long draw(){ return 10; }
 }
 interface Drawable
 {
 =A0int draw();
 }
In my opinion, C can derive from Drawable ideally. so, it will be satisfied with this code. static assert(isCovariantWith!(typeof(C.draw), typeof(Drawable.draw))); Correctness of it is like this, isn't it? class C { =A0int draw(){ return 10; } } interface Drawable { =A0long draw(); }
 The override should be legit.
I will fix them. Kenji Hara
Sep 23 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/23/10 14:13 CDT, kenji hara wrote:
 I supported covariance of return types.
 Please check it.
Excellent! And sorry, indeed I got it backwards: if the interface returns e.g. long, the implementation is allowed to return int. Generally if the interface returns T, the implementation is allowed to return any U implicitly convertible to T.
 2010/9/24 kenji hara<k.hara.pg gmail.com>:
 Thanks very much!

 If you agree, I am committed to advocate adopting this abstraction for Phobos
in module std.typecons, with credit.
Of couse, I agree.
Perfect, thanks! Stay tuned.
 All - a bit of bikeshedding - what is a better name for adaptTo? I know there
is a consecrated name for such late matching of an interface, but I can't
remember it.
from here(http://www.coderage.com/interfaces/), I found two keywords. - Non-intrusive dynamic polymorphism - Aspect Oriented Programming How about you?
Well the first term is, I think, invented by the author of the Interfaces Boost library, and the second is unrelated. I discussed your implementation with Walter and he recognized it as an instance of structural conformance. Indeed, check this paper that does the same for Java: http://tinyurl.com/2ct69t7. I think adaptTo should be therefore called structuralCast. Also, Kenji, I very much recommend you read this paper: http://tinyurl.com/2e3vmmx. It contains further idea on how you can extend structuralCast to multiple interfaces. I actually have some old code that might help there. Here are a few more suggestions for future work: * The object returned by structuralCast should offer the ability to access the original object, be it via an explicit function or an implicit mechanism such as alias this. * structuralCast should work with a struct as input. The object returned stores a copy of the struct inside and implements the interface in terms of calls to the struct's member functions. * structuralCast should work with a pointer to a struct as input and work as above, except it doesn't make a copy - it stores the pointer and forwards method calls to it. (This is unsafe.) * structuralCast should work to cast a struct to another. The requirements for accepting a structural cast from S to T are as follows: a) T must be a prefix of S, i.e. all fields in T appear in the same order and with the same names at the beginning of S. For example: struct Point2D { int x, y; } struct Point3D { int x, y, z; } struct Point2DColor { int x, y; Color color; } struct Point3DColor { int x, y, z; Color color; } In the example above, Point2D is a prefix of all others, and Point3D is a prefix of Point3DColor. b) All fields that are common to S and T must be public in both. structuralCast should not give access to private data and provide opportunity for breaking invariants. If these conditions are satisfied, then given a reference or a pointer to S, structuralCast gives you back (safely) a reference or a pointer to T. The implementation is a simple cast of pointers, but the point is that the function is trusted, i.e. it provides a safe restricted interface over the unsafe cast. Andrei
Sep 24 2010