-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Add pattern-variables.md #4592
Merged
Merged
Add pattern-variables.md #4592
Changes from 14 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
acd811f
Create pattern-variables.md
alrz efa5e0c
Update pattern-variables.md
alrz d9b438d
Update pattern-variables.md
alrz 044b4a8
Update pattern-variables.md
alrz ea92dc8
Update pattern-variables.md
alrz 49036d6
Update pattern-variables.md
alrz 1ba7b0c
Update pattern-variables.md
alrz ba99780
Update pattern-variables.md
alrz 30d72fb
Update pattern-variables.md
alrz 8c1e03a
Update pattern-variables.md
alrz 6f7afa1
Update pattern-variables.md
alrz 0b2945a
Update pattern-variables.md
alrz 65f7737
Update pattern-variables.md
alrz 1fe9041
Update pattern-variables.md
alrz c7e019c
Update pattern-variables.md
alrz 9ac4b5c
Update pattern-variables.md
alrz 43e54a1
Update pattern-variables.md
alrz ec77853
Update pattern-variables.md
alrz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# Variable declarations under disjunctive patterns | ||
|
||
## Summary | ||
|
||
Allow variable declarations under `or` patterns and across `case` labels in a `switch` section. | ||
|
||
## Motivation | ||
|
||
This feature would reduce code duplication where we could use the same piece of code if either of patterns is satisfied. For instance: | ||
```cs | ||
if (e is (int x, 0) or (0, int x)) | ||
Use(x); | ||
|
||
switch (e) | ||
{ | ||
case (int x, 0): | ||
case (0, int x): | ||
Use(x); | ||
alrz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
break; | ||
} | ||
``` | ||
Instead of: | ||
|
||
```cs | ||
if (e is (int x, 0)) | ||
Use(x); | ||
else | ||
alrz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Use(x) | ||
|
||
switch (e) | ||
{ | ||
case (int x, 0): | ||
Use(x); | ||
break; | ||
case (0, int x): | ||
Use(x); | ||
break; | ||
} | ||
``` | ||
|
||
## Detailed design | ||
|
||
Variables *must* be redeclared under all disjuncitve patterns because assignment of such variables depend on the order of evaluation which is undefined in the context of pattern-matching. | ||
|
||
- In a *disjunctive_pattern*, pattern variables declared under the left-hand-side must be redeclared under the right-hand-side. | ||
alrz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- In a *switch_section*, pattern variables declared under each case label must be redeclared under every other case label. | ||
|
||
In any other case, variable declaration follows the usual scoping rules and is disallowed. | ||
|
||
These names can reference either of variables based on the result of the pattern-matching at runtime. Under the hood, it's the same local being assigned in each pattern. | ||
|
||
Redeclaring pattern variables is only permitted for variables of the same type. | ||
|
||
## Unresolved questions | ||
|
||
- How identical these types should be? | ||
- Could we support variable declarations under `not` patterns? | ||
- Could we relax the scoping rules beyond pattern boundaries? | ||
```cs | ||
if (e is (int x, 0) || a is (0, int x)) | ||
``` | ||
- Could we relax the redeclaration requirement in a switch section? | ||
```cs | ||
case (int x, 0) a when Use(x, a): // ok | ||
case (0, int x) b when Use(x, b): // ok | ||
Use(x); // ok | ||
Use(a); // error; not definitely assigned | ||
Use(b); // error; not definitely assigned | ||
break; | ||
``` |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd add some more practical (less abstract) motivating examples.
Looking that the roslyn codebase, we often have a
switch
expression just to get some value out of different kinds of bound nodes. Many can be found just by searching for "node switch".But I have to say looking at that search result, most of them don't look like they would benefit from this feature (either they use
when
clauses for different cases, or they call different property/method overloads in the different cases).