On Tue, Jul 17, 2012 at 11:08 PM, David Piepgrass <qwertie...@gmail.com>wrote: > > I, too, was enamored with Go Interfaces and implemented them for .NET: > > http://www.codeproject.com/**Articles/87991/Dynamic-** > interfaces-in-any-NET-language<http://www.codeproject.com/Articles/87991/Dynamic-interfaces-in-any-NET-language>
Interesting, good article and project, thanks. And I wasn't the only one; later, someone else published another library > for .NET with the exact same goal. This is definitely a feature I would > want to see in D, preferably as a first-class feature, although sadly that > would break any code that relies on ISomething being pointer-sized; Go uses > fat pointers, and we use a thin-pointer implementation in .NET but it's > inefficient (as every cast creates a heap-allocated wrapper, and > double-indirection is needed to reach the real method.) > D has powerful template and CTFE, seems we have more choices, fat pointer or thin pointer. I didn't think seriously about the performance differences. About every cast creates a heap-allocated wrapper, I think we can try to use lower cost way in D. In my code: -- void opAssign(V)(GoInterface!(V) v) if (is(V == interface)) { //pragma(msg, "assign for GoInterface"); static if (isImplicitlyConvertible!(V, T)) { //pragma(msg, V.stringof ~ " can implicitly convert to " ~ T.stringof); m_impl = v.m_impl; } else static if (isImplicitlyConvertible!(T, V)) { //pragma(msg, T.stringof ~ " can implicitly convert to " ~ V.stringof ~ ", try dynamic cast"); if (v.m_impl is null) { m_impl = null; } else { m_impl = cast(T)(v.m_impl); if (m_impl is null) { // dynamic cast failed, try dynamic proxy m_impl = buildDynamicProxy!(V)(v); } } } else { //pragma(msg, "cannot implicitly between " ~ V.stringof ~ " and " ~ T.stringof); static if (isInterfaceConvertible!(V, T)) { //pragma(msg, "generate static proxy to convert " ~ V.stringof ~ " to " ~ T.stringof); m_impl = new StaticProxy!(V)(v.m_impl); } else { //pragma(msg, V.stringof ~ " not compatible " ~ T.stringof ~ ", must dynamic build call proxy"); m_impl = buildDynamicProxy!(V)(v); } } } -- Some cases we can directly do assignment, it also can be optimized to reduce heap allocation. > > Anyway, they say it's possible to build runtime reflection in D but I've > no idea how... has it never been done before? > Of course, runtime template instantiation won't be possible. Therefore, > run-time casting will have to be more limited than compile-time casting. > > Reflection to free functions would be really nice, but it might be less > capable at run-time. Consider if you there is a class A in third-party > module MA that you want to cast to interface I, but class A is missing a > function F() from I. So in your module (module MB) you define a free > function F(B) and now you can do the cast. I guess realistically this can > only happen at compile-time, since a run-time cast would naturally only > look in module MA, not MB, for functions it could use to perform the cast. > Presumably, it also requires that MA requested a run-time reflection table > to be built, and is it possible to build a reflection table for a module > over which you have no control? > Free functions support is hard, with runtime cast, I just think compile time. I am trying to support free functions at compile time, is also hard, since the generator in gointerface module, but other modules are only visible in the module that used these modules. I have an ugly implementation used compile time string mixin, trying to simplify it. Fighting.