Skip to content

Post-Parsing / Type conversion validation / constraint API #1241

Open
@henrygab

Description

@henrygab

[[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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions