On Wednesday, 13 October 2021 at 16:24:52 UTC, Steven
Schveighoffer wrote:
On 10/13/21 11:50 AM, Andrey Zherikov wrote:
On Wednesday, 13 October 2021 at 14:36:30 UTC, Steven [...]
No, it's not a confusion about `unused`. The `array` parameter
has the same issue.
I meant that for named parameters, one shouldn't have to
attribute them for them to be considered part of the parameters.
e.g. (to replace your current code):
```d
struct Params
{
// Positional arguments are required by default
@PositionalArgument(0) // override the default of a named
argument
string name;
// Named argments are optional by default
string unused = "some default value";
// Numeric types are converted automatically
int num;
// Boolean flags are supported
bool flag;
// Enums are also supported
enum Enum { unset, foo, boo };
@NamedArgument("enum") // required since enum is a keyword
Enum enumValue;
// Use array to store multiple values
int[] array;
// Callback with no args (flag)
void cb() {}
// Callback with single value
void cb1(string value) { assert(value == "cb-value"); }
// Callback with zero or more values
void cb2(string[] value) { assert(value ==
["cb-v1","cb-v2"]); }
}
```
The point is that I shouldn't have to tell the library the name
of something that I've already given a name to.
Having them named differently on the command line than the
actual field name should still be a possibility (and required
in some cases, e.g. the `enum` case above), but honestly, the
`Params` struct exists solely to accept command line
parameters, there's no compelling need to use alternate names
for the command line and the field name. If the library
automatically does the right thing by default, then your code
becomes simpler and more beautiful.
Not to detract from your library, because I think it's an
awesome design to model using structs (one I use all the time),
but the API developer in me frowns at lack of DRY. Try to focus
on requiring the smallest amount of machinery/attributes
possible. Every time you require extraneous pieces to get
things to work, it adds another place where errors/confusion
can happen.
-Steve
This should probably rather be:
```d
struct Params
{
// Positional arguments are required by default
@PositionalArgument(0) // override the default of a named
argument
string name;
// Named argments are optional by default
@NamedArgument
string unused = "some default value";
// Numeric types are converted automatically
@NamedArgument
int num;
// Boolean flags are supported
@NamedArgument
bool flag;
// Enums are also supported
enum Enum { unset, foo, boo };
@NamedArgument("enum") // required since enum is a keyword
Enum enumValue;
// Use array to store multiple values
@NamedArgument
int[] array;
// Callback with no args (flag)
@NamedArgument
void cb() {}
// Callback with single value
@NamedArgument
void cb1(string value) { assert(value == "cb-value"); }
// Callback with zero or more values
@NamedArgument
void cb2(string[] value) { assert(value ==
["cb-v1","cb-v2"]); }
}
```
as otherwise the definition could be ambiguous (like are the
parameters positional with automatic count or named by default?)
If you don't like the repetition you could also then make it
`@NamedArgument { [all my variables] }` But I'm not a fan of
having everything included even without UDA