Thread overview
How std.getopt would look with type functions
May 24, 2020
Stefan Koch
May 24, 2020
Stefan Koch
May 24, 2020
Adam D. Ruppe
May 24, 2020
Stefan Koch
May 24, 2020
Adam D. Ruppe
May 24, 2020
Basile B.
May 24, 2020
Just now I thought about one of the things that always irked me about variadic template parameter lists. The lack of type checking.
And the wired errors which are getting caught far too late in the template instance stack.

Let's take std.getopt as an example.
The first example givin in it's docs is this

 auto helpInformation = getopt(
    args,
    "length",  &length,    // numeric
    "file",    &data,      // string
    "verbose", &verbose,   // flag
    "color", "Information about this color", &color);    // enum

The pattern is clear it's a tuple representing {name, pointer_to_var} excpect when the second parameter is not a pointer but a string in which case it's {name, helptext pointer, to var} or maybe just forgot to pass another pointer to a var in there ? And "Information about this color" is just a very  long option name?

type functions can easily fix that.
Since they also introduce the ability to store references to symbols in structs.

struct arg { string name; alias var; string help = null }
getOps(args, arg("length", length),
             arg("file", data),
             arg("verbose", verbose),
             arg("color", color, "Information about this color")
);

I argue that this is firstly more type safe.
And secondly looks much nicer.
getopt could be defined as getopt(string args, arg[] args...)
and one could leave the fiddling to detect how to interpret which part of the argument list
out of the getopt implementation.
May 24, 2020
On Sunday, 24 May 2020 at 00:15:07 UTC, Stefan Koch wrote:
>
> struct arg { string name; alias var; string help = null }
> getOps(args, arg("length", length),
>              arg("file", data),
>              arg("verbose", verbose),
>              arg("color", color, "Information about this color")
> );
>

Ah wrong args[]... have to go into the template parameter list.
At least for now. it would look more like
getOps!(arg("length", length),
       arg("file", data),
       arg("verbose", verbose),
       arg("color", color, "Information about this color"))(args);

The point still stands though.
May 24, 2020
On Sunday, 24 May 2020 at 00:23:31 UTC, Stefan Koch wrote:

>
> Ah wrong args[]... have to go into the template parameter list.
> At least for now. it would look more like
> getOps!(arg("length", length),
>        arg("file", data),
>        arg("verbose", verbose),
>        arg("color", color, "Information about this color"))(args);

We can do this today (just the template args would be implicit).

May 24, 2020
On Sunday, 24 May 2020 at 00:15:07 UTC, Stefan Koch wrote:
> Just now I thought about one of the things that always irked me about variadic template parameter lists. The lack of type checking.
> And the wired errors which are getting caught far too late in the template instance stack.
>
> Let's take std.getopt as an example.
> The first example givin in it's docs is this
>
>  auto helpInformation = getopt(
>     args,
>     "length",  &length,    // numeric
>     "file",    &data,      // string
>     "verbose", &verbose,   // flag
>     "color", "Information about this color", &color);    // enum
>
> The pattern is clear it's a tuple representing {name, pointer_to_var} excpect when the second parameter is not a pointer but a string in which case it's {name, helptext pointer, to var} or maybe just forgot to pass another pointer to a var in there ?

No but there's an optional parameter that is that the flags can be overridden before each new serie of parameters, but well this is essentially a pattern... just add this to the tuple and adjust the flag so that "no flag" means "keep processing as previously".

> And "Information about this color" is just a very  long option name?
>
> type functions can easily fix that.
> Since they also introduce the ability to store references to symbols in structs.
>
> struct arg { string name; alias var; string help = null }
> getOps(args, arg("length", length),
>              arg("file", data),
>              arg("verbose", verbose),
>              arg("color", color, "Information about this color")
> );
>
> I argue that this is firstly more type safe.
> And secondly looks much nicer.
> getopt could be defined as getopt(string args, arg[] args...)
> and one could leave the fiddling to detect how to interpret which part of the argument list
> out of the getopt implementation.

I and others use UDA in a very similar fashion [1], which makes the driver of an application ridiculously nice looking [2].

[1] https://gitlab.com/basile.b/dexed/-/blob/4f63afb30a43b9ac52ba724f0518986e1490d1ff
/dastworx/src/main.d#L55
[2] https://gitlab.com/basile.b/dexed/-/blob/4f63afb30a43b9ac52ba724f0518986e1490d1ff/dastworx/src/main.d#L22

having the possibility to store a reference to a function or to a value without using pointers is a key feature for making getopt @safe BTW.
As a bonus, once you have direct access to the arguments targets the whole getopt processing can be adapted to the arguments, i.e static foreach (unrolling).
May 24, 2020
On Sunday, 24 May 2020 at 03:43:58 UTC, Adam D. Ruppe wrote:
> On Sunday, 24 May 2020 at 00:23:31 UTC, Stefan Koch wrote:
>
>>
>> Ah wrong args[]... have to go into the template parameter list.
>> At least for now. it would look more like
>> getOps!(arg("length", length),
>>        arg("file", data),
>>        arg("verbose", verbose),
>>        arg("color", color, "Information about this color"))(args);
>
> We can do this today (just the template args would be implicit).

Yes but that's no reason to not show how it would look?
May 24, 2020
On Sunday, 24 May 2020 at 07:06:31 UTC, Stefan Koch wrote:
> Yes but that's no reason to not show how it would look?

getopt(
   arg("whatever", "help", whatever),
   arg("other", other)
);

It is identical to what you wrote except with implicit template args. getopt there is still a variadic template, arg is a factory function (with two overloads, with and without the help string) that returns a templated struct. The getopt is free to static assert fail if an argument isn't  of the typeof(arg).

The final arg is either an explicit pointer or a ref argument that takes the address internally for the return value.

No fancy feature needed here.