vittorioromeo / scelta

(experimental) Syntactic sugar for variant and optional types.
https://vittorioromeo.info
MIT License
157 stars 10 forks source link

One `match` to rule them all #6

Closed vittorioromeo closed 6 years ago

vittorioromeo commented 6 years ago

Added an homogeneous scelta::match statement that adapts to both non-recursive and recursive pattern matching.

The idea is that this should be the "go-to match function", unless the user explicitly needs non-recursive/recursive match.

From the README:

After defining recursive structures, in place recursive visitation is also possible. scelta provides two ways of performing recursive visitation:

  • scelta::match(/* base cases */)(/* recursive cases */)(/* visitables */)

    This is an "homogeneous" match function that works for both non-recursive and recursive visitation. The first invocation always takes an arbitrary amount of base cases. If recursive cases are provided to the second invocation, then a third invocation with visitables is expected. Unless explicitly provided, the return type is deduced from the base cases.

    The base cases must have arity N, the recursive cases must have arity N + 1. N is the number of visitables that will be provided.

  • scelta::recursive::match</* return type */>(/* recursive cases */)(/* visitables */)

    This version always requires an explicit return type and an arbitrary amount of recursive cases with arity N + 1, where N is the number of visitables that will be provided.

int_tree t0{/*...*/};

scelta::match(
    // Base case.
    [](int x){ cout << x; }
)(
    // Recursive case.
    [](auto recurse, int_tree_vector v){ for(auto x : v) recurse(v); }
)(t0);

// ... or ...

scelta::recursive::match<return_type>(
    // Base case.
    [](auto, int x){ cout << x; },

    // Recursive case.
    [](auto recurse, int_tree_vector v){ for(auto x : v) recurse(v); }
)(t0);