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