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

aliak something at something.com
Sat Mar 14 16:42:11 UTC 2020


On Saturday, 14 March 2020 at 15:34:53 UTC, Adam D. Ruppe wrote:
> 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.

Why does it scare you?

I know pollution is the point of a mixin, and mixin is the only 
way in D to get the context. And I'm not a fan of pollution, 
which is why a solution that doesn't pollute a scope is preferred 
- yes you cam be careful to avoid accidental pollution. But you 
can't guarantee it.

If you want certain functionality, and your two options is one 
that involves possible pollution and one that doesn't, I'd always 
take the non-pollution route.

>
>>   return caller.stringof;
>

Yeah agreed.

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

There were a number of approaches I went through first

1) Mixin template
   * Awkward syntax (mixin a thing, then know what the thing is 
that was mixed in)
   * Could potentially put unwanted stuff in my scope
   * No way for code-reader to know how the mixin is changing the 
scope, making maintainability more cumbersome. You can go and 
look it up, but it's likely you'll miss something and also having 
to look up things for no reason is annoying when avoidable.
   * Having to always mixin something into your struct if you can 
get it automated seems unnecessary. Sure you can do it, but why 
when it can be avoided?

2) Explicitly passing in the context
   * Copy/pasta error prone.
   * Extra typing when maybe unnecessary
   * You can pass in the wrong context and the parse function will 
never be the wiser

The mixin soluton I tried was in place, not in the struct scope 
though. As you've already pointed out, putting in a mixin at 
struct level will not work because the top level is a function 
(but that can be worked around)

>
>> 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

That also wouldn't work in main().

>
> 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.

Hehe yeah, tried that too :) That'd work in main() but not inside 
a Command struct.

This'll work though:

int a;
parse!(__traits(parent, __traits(parent, a)));

Courtesy of Seven from the slack link.




More information about the Digitalmars-d mailing list