On Thursday, 17 March 2022 at 19:07:28 UTC, H. S. Teoh wrote:
Using independent, orthogonal UDAs may make option specification using your module easier to read. For example, from your docs:

        struct T {
                @(NamedArgument
.PreValidation!((string s) { return s.length > 1 && s[0] == '!'; })
                        .Parse        !((string s) { return s[1]; })
                        .Validation   !((char v) { return v >= '0' && v <= '9'; 
})
                        .Action !((ref int a, char v) { a = v - '0'; })
                )
                int a;
        }

could be rewritten with multiple UDAs as:

        struct T {
                @NamedArgument
@PreValidation!((string s) { return s.length > 1 && s[0] == '!'; })
                @Parse        !((string s) { return s[1]; })
                @Validation   !((char v) { return v >= '0' && v <= '9'; })
                @Action!((ref int a, char v) { a = v - '0'; })
                int a;
        }

It might also simplify your implementation by having more smaller, independent pieces for each UDA instead of a single complex UDA that handles everything.

I use UDAs extensively in my project and I've historically been doing the multiple-UDA approach you describe. Upon seeing argparse a few months back I started rewriting it to use a single UDA, and I found it allowed for a simpler implementation (and not the other way around).

The immediate gains boiled down to that I could now pass what is essentially a context struct around at CTFE instead of keeping track of multiple variables. Default values are also much easier to manage with much fewer `hasUDA`s sprinkled everywhere.

One drawback is documentation; adrdox does *not* like these kinds of UDAs.

Reply via email to