New idiom for scala-like implicits while trying to make mixin expressions.

Adam D. Ruppe destructionator at gmail.com
Sat Mar 14 15:34:53 UTC 2020


On Saturday, 14 March 2020 at 14:03:25 UTC, aliak wrote:
> workaround with a very nice added advantage that there's no way 
> for the workaround to pollute the calling scope (whereas a 
> mixin can).

This scares me, since "polluting" the calling scope is the entire 
point of a template mixin - to mix in its members.

>   return caller.stringof;

Similarly, any use of stringof is a red flag to me. Super buggy 
and indicates a good chance you are trying to pound a square peg 
into a round hole.


So let me look at your big picture goal and see if there's an 
entirely different approach....

> Basically, I was trying to figure out how to parse the command 
> line and allow the parser to know which command line "command" 
> it was being called from [0], and then I ended up with this 
> pattern for each cli command:

I'd either make the `parse` function be a member of the struct 
(which can be mixed in inside the struct if you like) or just 
simply be passed an instance/object.

mixin template Parse() {
     ParsedOptions parse(string[] args) {
         // note that you can simply use `this` in here!
     }
}

struct Command {
       /* stuff */
       mixin Parse;
}

Anywhere you mixin as the member function, the parse function 
will see the appropriate `this` and can go off on that.

However, that won't work top-level, since a module doesn't have 
`this`. I'm OK with that; it is simple enough to wrap commands in 
a struct anyway. But you could also abstract that a wee bit more 
too and have like

static if(is(typeof(this))
   alias t = this; // use this
else
   alias t = mixin(__MODULE__); get reference to module

// use t from here on.


but the wrapper is easy enough to me, I like putting all the 
commands in a struct anyway.


Or alternatively, of course, you can:

auto parsedOptions = parse!(typeof(this))(args); // explicitly 
pass context


In either case, it doesn't know which specific function it is 
called from, but it knows the object, which is what it really 
wants anyway! Then you can look at the members, including 
sub-commands to go down the whole tree.

You could also explicitly pass `parse!(__traits(parent, 
{}))(args)` to pass the specific function.



More information about the Digitalmars-d mailing list