Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement pattern guards #1910

Merged
merged 3 commits into from
May 13, 2024
Merged

Implement pattern guards #1910

merged 3 commits into from
May 13, 2024

Conversation

yannham
Copy link
Member

@yannham yannham commented May 6, 2024

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.

This commit implement 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. This condition is introduced by the
(already existing) `if` keyword. For example:

`match { {list} if list != [] => body }` will match a record with a
unique field `list` that isn't empty.

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).
@yannham yannham requested review from jneem and vkleen May 6, 2024 16:21
@github-actions github-actions bot temporarily deployed to pull request May 6, 2024 16:24 Inactive
core/src/term/mod.rs Outdated Show resolved Hide resolved
core/src/term/pattern/compile.rs Show resolved Hide resolved
@github-actions github-actions bot temporarily deployed to pull request May 13, 2024 08:57 Inactive
@yannham yannham requested a review from jneem May 13, 2024 10:25
@github-actions github-actions bot temporarily deployed to pull request May 13, 2024 10:28 Inactive
@yannham yannham added this pull request to the merge queue May 13, 2024
Merged via the queue into master with commit 7225b72 May 13, 2024
5 checks passed
@yannham yannham deleted the feat/pattern-guards branch May 13, 2024 15:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants