tweag / nickel

Better configuration for less
https://nickel-lang.org/
MIT License
2.23k stars 85 forks source link

Implement pattern guards #1910

Closed yannham closed 1 month ago

yannham commented 2 months ago

This PR implements pattern guards, which are side conditions that can be added to the branch of a match expression, following the pattern, to further constrain the matching. A guard is introduced by the (already existing) if keyword. For example:

nickel> {list = std.array.generate std.function.id 20}
|> match {
  {list} if std.array.length list > 10 => 'Big,
  {list} if list == [] => 'Empty,
  {list} => 'Small
}
'Big

nickel>

The compilation is rather straightforward, as a pattern is already compiled to a tree of if-then-else while also building the bindings introduced by pattern variables. After all the conditions coming from the pattern have been tested, we just additionally check for the guard (injecting the bindings in the condition since the guard can - and most often does - use variables bound by the pattern).

I expect this feature to be particularly nice for writing custom contracts, which are currently in practice sizeable nested if-then-else trees, which could hopefully be aggressively flattened with patterns and guards.