Thread overview
Using . notation abstractly
Oct 10, 2018
James Japherson
Oct 11, 2018
Simen Kjærås
Oct 12, 2018
Paul Backus
Oct 12, 2018
Simen Kjærås
October 10, 2018
struct Dispatcher(Base...)
{
    static auto opDispatch(string name, T...)(T vals)
	{
		pragma(msg, " - ", name);

		
		return Dispatcher!(Base, name).init;

    }

}
struct Dispatch
{
	alias X = Dispatcher!void;
	alias X this;
}

pragma(msg, Dispatch.A.B.C, " - ", typeof(Dispatch.A.B.C));


CT Output:

 - A
 - B
 - C
Dispatcher() - Dispatcher!(void, "A", "B", "C")



The idea is one can do

Dispatch.Left.Right.A.B.C;

and it will sequentially handle all the indirections regardless of how many and return an object that encodes the path. (which then can be collapsed down to a single string).

Ultimately some action can then be taken on the path.

The point of all this is because D does not allow nesting of enums

which allows for nice use of . to separate hiearchies:

enum A
{
   enum B
   {
      X,
   }
}

A.B.X, rather than having to have one large flat enum and do things like A_B_X.

I know one can use structs but it is messy and not general enough.

Dispatch.A.B.X

can be used such as

struct A
{
    alias Dispatch this;
}

A.B.X

but it requires more machinery to setup.

The purpose is mainly to be able to hijack the `.` notation to create nice separations visually like we do for indirection but allow it to mean many different things.

One of the problems is connecting it with actual code that does something depending on the path in a way that is general enough to be used for a wide variety of problems.

Any ideas on how this could be done?







October 11, 2018
On Wednesday, 10 October 2018 at 22:56:14 UTC, James Japherson wrote:
> One of the problems is connecting it with actual code that does something depending on the path in a way that is general enough to be used for a wide variety of problems.
>
> Any ideas on how this could be done?

My first idea is to have Dispatch take an alias parameter, and see if it's useful for anything:

struct Dispatch(alias Fn, Base...) {
    static auto opDispatch(string name, T...)(T vals) {
        return Dispatch!(Fn, Base, name).init;
    }
    alias _get = Fn!Base;
    alias _get this;
}

// join a list of stuff with _ between each element.
template join(T...) {
    import std.conv : to;
    static if (T.length == 0) {
        enum join = "";
    } else static if (T.length == 1) {
        enum join = T[0].to!string;
    } else {
        enum join = T[0].to!string ~"_"~join!(T[1..$]);
    }
}

unittest {
    assert(Dispatch!join.A.B.C == "A_B_C");
}

No idea what to use it for, but it's kinda nice, I guess. Very generic, too.

--
  Simen
October 12, 2018
On Wednesday, 10 October 2018 at 22:56:14 UTC, James Japherson wrote:
> The point of all this is because D does not allow nesting of enums
>
> which allows for nice use of . to separate hiearchies:
>
> enum A
> {
>    enum B
>    {
>       X,
>    }
> }
>
> A.B.X, rather than having to have one large flat enum and do things like A_B_X.

You can use a mixin template to introduce a new namespace:

https://run.dlang.io/is/K0kJJl


October 12, 2018
On Friday, 12 October 2018 at 12:43:53 UTC, Paul Backus wrote:
> On Wednesday, 10 October 2018 at 22:56:14 UTC, James Japherson wrote:
>> The point of all this is because D does not allow nesting of enums
>>
>> which allows for nice use of . to separate hiearchies:
>>
>> enum A
>> {
>>    enum B
>>    {
>>       X,
>>    }
>> }
>>
>> A.B.X, rather than having to have one large flat enum and do things like A_B_X.
>
> You can use a mixin template to introduce a new namespace:
>
> https://run.dlang.io/is/K0kJJl

True, but D has namespaces elsewhere, which don't require you to clutter some other namespace with your enums:

struct A {
    enum B {
        X,
    }
}

final abstract class C {
    enum D {
        Y,
    }
}

This has the added benefits of 1) being more obvious, and 2) you can put other stuff in there.

On Wednesday, 10 October 2018 at 22:56:14 UTC, James Japherson wrote:
> I know one can use structs but it is messy and not general enough.

Please do elucidate - what do you mean not general enough? When is a struct less general than an enum?


> struct A
> {
>     alias Dispatch this;
> }
> 
> A.B.X
> 
> but it requires more machinery to setup.

Also:

alias A = Dispatch;
A.B.X;


Note that this results in Dispatcher!("B", "X"), so you'll have to pass the "A" manually (the same problem exists in your code above):

alias A = Dispatcher!"A";
A.B.X; // Dispatcher!("A", "B", "X")

--
  Simen