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

Reply via email to