emulate with

Amex Amex at gmail.com
Fri May 31 16:17:41 UTC 2019


On Friday, 31 May 2019 at 08:35:23 UTC, Simen Kjærås wrote:
> On Friday, 31 May 2019 at 07:17:22 UTC, Amex wrote:
>> What I'm talking about is that if A would be dispatched to, 
>> say, W!X where W handles the special dispatching by returning 
>> X_A rather than X.A.
>>
>>
>> I don't know if D can do this kinda stuff even though it would 
>> be rather simple as it would depend on with.
>
> Of course D can! However, it's not really pretty, and I think I 
> found a bug in the process.
>
> This is my code that compiles and runs:
>
> void X_A(int i) {}
> void X_A(string s) {}
> void X_B(int i) {}
> void X_C_Q(int i) {}
>
> unittest {
>     with (Dispatcher.X!({})) {
>         A(1);
>         A("a");
>         B(2);
>         C_Q(3);
>     }
> }
>
> template getMethod(alias x, string name) {
>     static if (__traits(hasMember, x, name)) {
>         alias getMethod = __traits(getMember, x, name);
>     } else static if (x.stringof[0..7] == "module ") {
>         import std.meta : AliasSeq;
>         alias getMethod = AliasSeq!();
>     } else {
>         alias getMethod = getMethod!(__traits(parent, x), name);
>     }
> }
>
> struct Dispatcher {
>     template opDispatch(string prefix) {
>         static auto opDispatch(alias context)() {
>             struct WithObject {
>                 auto opDispatch(string name, A...)(A a) {
>                     struct OverloadCaller {
>                         auto opCall(Args...)(Args args) {
>                             return getMethod!(context, 
> prefix~"_"~name)(args);
>                         }
>                     }
>                     OverloadCaller result;
>                     return result;
>                 }
>             }
>             return WithObject();
>         }
>     }
> }
>
> So, the ugly:
>
> 1) Instead of just Dispatcher.X, we need to give Dispatcher a 
> context from where to look for X_<something>. That's the curly 
> brackets in Dispatcher.X!({}).
>
> 2) The bug I mentioned. The whole OverloadCaller deal is a 
> silly workaround for WithObject's opDispatch not being called 
> correctly by DMD. That's also why WithObject's opDispatch takes 
> (A...)(A a). I'll be filing this, of course.
>
> 3) with doesn't correctly handle static opDispatch. I'll be 
> filing a bug for that as well.
>
> We could fix 1) by introducing a new magic identifier - 
> something like __CONTEXT__, which would work somewhat like 
> __FUNCTION__, but be useful for reflection with __traits. I've 
> played a little with this idea, but I'm not ready to make a PR 
> with it.
>
> With 1), 2) and 3) fixed, the code would look like this (only 
> changed code included):
>
> unittest {
>     with (Dispatcher.X) {
>         A(1);
>         A("a");
>         B(2);
>         C_Q(3);
>     }
> }
>
> struct Dispatcher {
>     struct opDispatch(string prefix, alias context = 
> __CONTEXT__) {
>         static auto opDispatch(string name, Args...)(Args args) 
> {
>              return getMethod!(context, prefix~"_"~name)(args);
>         }
>     }
> }
>
> I think that's kinda neat, TBH.
>
> --
>   Simen


Thanks, I haven't messed with it but it by your examples it 
should do what I want...

I actually probably need the use of .'s turned in to _'s... so I 
can write stuff like

A.B.C.D and it all goes to X.A_B_C_D.

I'm not sure if A.B.C.D would get dispatched as a whole or just 
in part though(e.g., is it treated as A.(B.(C.D)) or (A.B).C).D 
or A.B.C.D) which would require some type of chaining dispatcher 
I guess).

In any case it helps with my specific problem. I like the idea of 
_CONTEXT_ and it might be usable in other areas.

Thanks.


More information about the Digitalmars-d-learn mailing list