www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using . notation abstractly

reply James Japherson <JJ goolooking.com> writes:
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?
Oct 10 2018
next sibling parent Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
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
Oct 11 2018
prev sibling parent reply Paul Backus <snarwin gmail.com> writes:
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
Oct 12 2018
parent Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
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
Oct 12 2018