www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - compile time class introspection?

reply serg <why.you.need my.email> writes:
Is there any way to find out if a template parameter has method?

I was naively hoped for tupleof to help, but it seems not =(

-- serg.
Jun 14 2007
parent reply serg <why.you.need my.email> writes:
What really want is, to have a template mixin method that depending on class it
inserted into, could call internally a member method if it available.

Something like this:

template dispatchT(T)
{
    void dispatch(int msg)
    {
        switch (msg)
        {
        case WM_CLOSE:
            static if (OnClose in T) // <-- T has desired method
                return OnClose();
            static else
                break;
        case WM_DESTROY:
            static if (T.OnDestroy) // <-- same, but different syntax
                return OnDestroy();
            static else
                break;
        default:
        }
        return DefWndProc();
    }
}

class Window
{
    void OnClose(){}
    void OnDestroy(){}
    mixin dispatchT!(Window);
}


-- serg.
Jun 14 2007
next sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
class A { void foo() {} }
class B { void bar() {} }

A a;
B b;

assert( is( typeof(&a.foo) ) );
assert( is( typeof(&b.bar) ) );
assert(!is( typeof(&a.bar) ) );
assert(!is( typeof(&b.foo) ) );

Or something like that.

	-- Daniel
Jun 14 2007
prev sibling parent reply Max Samukha <samukha voliacable.com.removethis> writes:
On Thu, 14 Jun 2007 09:27:50 -0400, serg <why.you.need my.email>
wrote:

What really want is, to have a template mixin method that depending on class it
inserted into, could call internally a member method if it available.

Something like this:

template dispatchT(T)
{
    void dispatch(int msg)
    {
        switch (msg)
        {
        case WM_CLOSE:
            static if (OnClose in T) // <-- T has desired method
                return OnClose();
            static else
                break;
        case WM_DESTROY:
            static if (T.OnDestroy) // <-- same, but different syntax
                return OnDestroy();
            static else
                break;
        default:
        }
        return DefWndProc();
    }
}

class Window
{
    void OnClose(){}
    void OnDestroy(){}
    mixin dispatchT!(Window);
}


-- serg.

You might do it like this: template dispatchT(T) { void dispatch(int msg) { switch (msg) { static if (is(typeof(T.OnClose))) { case WM_CLOSE: return T.OnClose(); } else static if (is(typeof(T.OnDestroy))) { case WM_DESTROY: return T.OnDestroy(); } default: } } }
Jun 14 2007
parent reply serg <why.you.need my.email> writes:
Max Samukha Wrote:
 You might do it like this:
 ...
             static if (is(typeof(T.OnClose)))
 ...

Yes, this is exactly what I was looked for! Thanks, Max! -- serg.
Jun 14 2007
parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
serg wrote:
 Max Samukha Wrote:
 You might do it like this:
 ...
             static if (is(typeof(T.OnClose)))
 ...

Yes, this is exactly what I was looked for! Thanks, Max! -- serg.

This is an important thing about D that probably deserves a long and extensive tutorial somewhere... Many of its cooler features aren't really features at all, but side-effects of other more general features. So, to reuse this same example, no D doesn't have a way to ask if a class or structure has a particular method. D /does/ have a way to check for valid types... which, incidentally, non-existant members are invalid types. So, voila, a side-effect of checking its type is that you confirm it exists. There are others... a plethora, even. Walter is fond of lots of small things that can be put together to achieve amazing things -- and I don't strictly disagree -- but it isn't usually obvious what you can do with those nifty little gadgets. -- Chris Nicholson-Sauls
Jun 14 2007
parent reply Serg Kovrov <kovrov bugmenot.com> writes:
Chris Nicholson-Sauls wrote:
 This is an important thing about D that probably deserves a long and 
 extensive tutorial somewhere...  Many of its cooler features aren't 
 really features at all, but side-effects of other more general features. 

I hope it won't happen. Let me explain.. Considered to be a side-effect (or hack), this rather should be redesigned than teaching in docs/tutorials/books. That way we end up with yet another C++ Its sad that I actually will use this hack (that is, will produce code I'm not proud with). I can't just hope and wait for this to be fixed (properly designed), as temptation to have this functionality is to strong. PS. Don't get me wrong, I really do like D -- serg.
Jun 14 2007
parent reply janderson <askme me.com> writes:
Serg Kovrov wrote:
 Chris Nicholson-Sauls wrote:
 This is an important thing about D that probably deserves a long and 
 extensive tutorial somewhere...  Many of its cooler features aren't 
 really features at all, but side-effects of other more general features. 

I hope it won't happen. Let me explain.. Considered to be a side-effect (or hack), this rather should be redesigned than teaching in docs/tutorials/books. That way we end up with yet another C++ Its sad that I actually will use this hack (that is, will produce code I'm not proud with). I can't just hope and wait for this to be fixed (properly designed), as temptation to have this functionality is to strong. PS. Don't get me wrong, I really do like D -- serg.

I disagree, I think an orthogonal design like D is a good thing in many cases. It means that you don't have to learn so many keywords and are more likely to determine the syntax yourself. It also means code is generally easier to maintain due to generalization because you can often reuse the code in more different ways then originally intended. I don't regard the solution given as a hack it seems pretty obvious to me. Either way it would have to be documented. If you don't like it, write a wrapper template. Also I don't think good orthogonality means the language has to get more complex. I think its about making the common coding primitives easy to use however also making them powerful enough if the user wants to extend them to something that is less common. -Joel
Jun 14 2007
parent reply Serg Kovrov <kovrov bugmenot.com> writes:
janderson wrote:
 I disagree, I think an orthogonal design like D is a good thing in many 
 cases.  It means that you don't have to learn so many keywords and are 
 more likely to determine the syntax yourself.  It also means code is 
 generally easier to maintain due to generalization because you can often 
   reuse the code in more different ways then originally intended.
 
 I don't regard the solution given as a hack it seems pretty obvious to 
 me.  Either way it would have to be documented.  If you don't like it, 
 write a wrapper template.
 
 Also I don't think good orthogonality means the language has to get more 
 complex.  I think its about making the common coding primitives easy to 
 use however also making them powerful enough if the user wants to extend 
 them to something that is less common.
 
 -Joel

I'm not sure I understand what you mean by "orthogonal design", and what it has to do with code reuse? I was talking about language facilities, something not available as user or library code. I just want to say I like idea of language features to be thoughtfully designed, as opposite to accidentally discovered side-effects. I have to say I don't really care about actual origin of a feature, but rather what it feels like. -- serg.
Jun 15 2007
next sibling parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Serg Kovrov wrote:
 janderson wrote:
 I disagree, I think an orthogonal design like D is a good thing in 
 many cases.  It means that you don't have to learn so many keywords 
 and are more likely to determine the syntax yourself.  It also means 
 code is generally easier to maintain due to generalization because you 
 can often   reuse the code in more different ways then originally 
 intended.

 I don't regard the solution given as a hack it seems pretty obvious to 
 me.  Either way it would have to be documented.  If you don't like it, 
 write a wrapper template.

 Also I don't think good orthogonality means the language has to get 
 more complex.  I think its about making the common coding primitives 
 easy to use however also making them powerful enough if the user wants 
 to extend them to something that is less common.

 -Joel

I'm not sure I understand what you mean by "orthogonal design", and what it has to do with code reuse? I was talking about language facilities, something not available as user or library code. I just want to say I like idea of language features to be thoughtfully designed, as opposite to accidentally discovered side-effects. I have to say I don't really care about actual origin of a feature, but rather what it feels like. -- serg.

I'm not positive that the side-effect in this case at least was accidental. I seem to recall it was specifically made sure to work in the development of is() expressions. (Could be wrong, it might've been talked about later.) That said, I do hear you, and actually personally wish reflection capabilities had their own access point of some kind. I'd even live with a new keyword to activate that access -- in my opinion it'd be worth it. Maybe a typeinfo() primitive alongside typeof() and typeid()... although that might be misleading since the objects returned by typeid() are descendants of the class TypeInfo; heh. Or maybe just the obvious reflect(), which would return an object like typeid() does, but a TypeView or TypeInspect or somesuch. Then provide reflection capabilities by way of that special class. In respect to that, maybe there should be an equivelant 'reflected' or 'reflect' (note the missing parentheses) attribute for marking a class as available for reflection. That way we only include the extra information in cases where its deemed useful... And now I'm at the point where I really should have started a new thread. So I'll shut up now. :) -- Chris Nicholson-Sauls
Jun 15 2007
parent Christopher Wright <dhasenan gmail.com> writes:
Chris Nicholson-Sauls wrote:
 Serg Kovrov wrote:
 janderson wrote:
 I disagree, I think an orthogonal design like D is a good thing in 
 many cases.  It means that you don't have to learn so many keywords 
 and are more likely to determine the syntax yourself.  It also means 
 code is generally easier to maintain due to generalization because 
 you can often   reuse the code in more different ways then originally 
 intended.

 I don't regard the solution given as a hack it seems pretty obvious 
 to me.  Either way it would have to be documented.  If you don't like 
 it, write a wrapper template.

 Also I don't think good orthogonality means the language has to get 
 more complex.  I think its about making the common coding primitives 
 easy to use however also making them powerful enough if the user 
 wants to extend them to something that is less common.

 -Joel

I'm not sure I understand what you mean by "orthogonal design", and what it has to do with code reuse? I was talking about language facilities, something not available as user or library code. I just want to say I like idea of language features to be thoughtfully designed, as opposite to accidentally discovered side-effects. I have to say I don't really care about actual origin of a feature, but rather what it feels like. -- serg.

I'm not positive that the side-effect in this case at least was accidental. I seem to recall it was specifically made sure to work in the development of is() expressions. (Could be wrong, it might've been talked about later.) That said, I do hear you, and actually personally wish reflection capabilities had their own access point of some kind. I'd even live with a new keyword to activate that access -- in my opinion it'd be worth it. Maybe a typeinfo() primitive alongside typeof() and typeid()... although that might be misleading since the objects returned by typeid() are descendants of the class TypeInfo; heh. Or maybe just the obvious reflect(), which would return an object like typeid() does, but a TypeView or TypeInspect or somesuch. Then provide reflection capabilities by way of that special class. In respect to that, maybe there should be an equivelant 'reflected' or 'reflect' (note the missing parentheses) attribute for marking a class as available for reflection. That way we only include the extra information in cases where its deemed useful... And now I'm at the point where I really should have started a new thread. So I'll shut up now. :)

Why not just improve .classinfo and apply it to structs as well? You'd want to rename it, probably...but if vtbl were an associative array of functioninfo[char[]] instead of a void*[], with a functioninfo definition including: - argument type tuple / array - return type - protection - static / nonstatic - pointer to classinfo, or null if it's a free function - pointer to the function Overload opAssign so you can reassign functions at need, maybe, and then keep the pointer as read-only externally. Do something similar with the members. Of course flectioned does this. And flectioned is pretty much what the builtin reflection of D should hope to be.
Jun 15 2007
prev sibling parent janderson <askme me.com> writes:
Serg Kovrov wrote:
 janderson wrote:
 I disagree, I think an orthogonal design like D is a good thing in 
 many cases.  It means that you don't have to learn so many keywords 
 and are more likely to determine the syntax yourself.  It also means 
 code is generally easier to maintain due to generalization because you 
 can often   reuse the code in more different ways then originally 
 intended.

 I don't regard the solution given as a hack it seems pretty obvious to 
 me.  Either way it would have to be documented.  If you don't like it, 
 write a wrapper template.

 Also I don't think good orthogonality means the language has to get 
 more complex.  I think its about making the common coding primitives 
 easy to use however also making them powerful enough if the user wants 
 to extend them to something that is less common.

 -Joel

I'm not sure I understand what you mean by "orthogonal design", and what it has to do with code reuse? I was talking about language facilities, something not available as user or library code.

Take the example of D's arrays. They all work the same across the whole language. One syntax applied across many different uses. If you wish to change the type of the array, you don't have to change your interface to users, or search replace loads of code. Furthermore, you don't have to write so many specialized templates. That's what I mean by generalization resulting in more reusable code.
 
 I just want to say I like idea of language features to be thoughtfully 
 designed, as opposite to accidentally discovered side-effects. I have to 
 say I don't really care about actual origin of a feature, but rather 
 what it feels like.
 
 -- serg.

I think a good orthogonal language is thoughtfully designed and things aren't accidentally discovered, they are simply logically discovered. Its like lego, you can make a million things from it with good building blocks. -Joel
Jun 15 2007