Description
[[Moving to new issue per @jonsequitur request]]
The current method to add constraints is too complex -- for example, the current suggestions require the user to re-parse the tokens and understand how to iterate though the internal data structures. Ouch.
Strawman goals / Scenarios (click to expand)
Goals
- Solution is invisible to clients which do not require the functionality
- Minimize code duplication
- Requires clients to writes minimal logic required for their particular use case
- Chainable / buildable ... user can add multiple constraints to an
Option
Scenarios
- User wants to further restrict an already-supported type, validating individual values
- User wants to further restrict sets of values (for -arity > 1)
Strawman client code usage (click to expand)
OK, this uses really long names, solely to be more descriptive.
Framework-provided names would likely be much shorter.
new Option<int[]>("-o")
.AddConstraintPerValue(IsPositiveValue)
.AddConstraintPerSet(ValuesAllEvenOrAllOdd);
new Option<string[]>("-s")
.AddConstraintPerValue(StartsWithVowel)
.AddConstraintPerSet(AllStartWithSameLetter);
Strawman per-value constraints (click to expand)
The idea here is that, even if Arity
maximum is greater than one, the library would take care of iterating.
public static bool IsPositiveValue(int value) { return value > 0; }
public static bool StartsWithVowel(string value) {
if (String.IsNullOrEmpty(value)) { return false; }
char tmp = Char.ToLowerInvariant(value[0]);
return (tmp == 'a' || tmp == 'e' || tmp == 'i' || tmp == 'o' || tmp == 'u' || tmp == 'y');
}
Strawman per-set-of-values constraints (click to expand)
The use of IOrderedEnumerable<T>
provides flexibility for the library to change the underlying data representation, while ensuring the order of the types matches what was passed via the command line.
The implementations are still simple, iterating through the provided set of values.
public static bool ValuesAllEvenOrAllOdd(IOrderedEnumerable<int> values ) {
bool any = false;
bool areEven;
foreach (var v in values) {
if (!any) { areEven = ((v % 2) == 0); }
if (areEven && ((v % 2) != 0)) { return false; }
else if ((v % 2) == 0) { return false; }
}
// return any; // returns false for zero entries
return true; // returns true for zero entries
}
public static bool AllStartWithSameLetter(IOrderedEnumerable<string> values) {
bool any = false;
char firstLetter;
foreach (var v in values) {
if (String.IsNullOrEmpty(v)) { return false; }
if (!any) { firstLetter = v[0]; }
if (v[0] != firstLetter) { return false; }
}
// return any; // returns false for zero entries
return true; // returns true for zero entries
}
I think this would be significantly improved experience for clients. Please consider making it simpler for the client code by enabling something such as the above?