-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Allow an optional vert at the beginning of a match branch #1925
Merged
Merged
Changes from 9 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
eebfbf7
Allow an optional vert at the beginning of a match branch
mdinger 17672dc
Extend comments about example B slightly
mdinger 95ae404
Add some information about how the grammar should
mdinger 0bba3c0
Trim whitespace
mdinger 23957e9
Rewrite to avoid styling topic
mdinger 548f6ef
Remove extraneous mains. Add the trailing vert to the grammar
mdinger 6a30871
Improve minor inconsistencies
mdinger ed12656
Update the teaching example for trailing verts
mdinger d75cf5e
Remove trailing vert inclusion
mdinger e3eda65
Trailing vert nit
mdinger 3b052a6
Backtick nit
mdinger e64560c
RFC 1925: Allow an optional vert at the beginning of a match branch
aturon 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,257 @@ | ||
- Feature Name: `match_vert_prefix | ||
- Start Date: 2017-02-23 | ||
- RFC PR: (leave this empty) | ||
- Rust Issue: (leave this empty) | ||
|
||
# Summary | ||
[summary]: #summary | ||
|
||
This is a proposal for the rust grammar to support a vert `|` at the | ||
beginning of the pattern. Consider the following example: | ||
|
||
```rust | ||
use E::*; | ||
|
||
enum E { A, B, C, D } | ||
|
||
// This is valid Rust | ||
match foo { | ||
A | B | C | D => (), | ||
} | ||
|
||
// This is an example of what this proposal should allow. | ||
match foo { | ||
| A | B | C | D => (), | ||
} | ||
``` | ||
|
||
# Motivation | ||
[motivation]: #motivation | ||
|
||
This is taking a feature which is nice about `F#` and allowing it by a | ||
straightforward extension of the current rust language. After having used | ||
this in `F#`, it seems limiting to not even support this at the language | ||
level. | ||
|
||
## `F#` Context | ||
|
||
In `F#`, enumerations (called `unions`) are declared in the following fashion where | ||
all of these are equivalent: | ||
|
||
```F# | ||
// Normal union | ||
type IntOrBool = I of int | B of bool | ||
// For consistency, have all lines look the same | ||
type IntOrBool = | ||
| I of int | ||
| B of bool | ||
// Collapsing onto a single line is allowed | ||
type IntOrBool = | I of int | B of bool | ||
``` | ||
|
||
Their `match` statements adopt a similar style to this. Note that every `|` is aligned, | ||
something which is not possible with current Rust: | ||
|
||
```F# | ||
match foo with | ||
| I -> "" | ||
| B -> "" | ||
``` | ||
|
||
## Maximizing `|` alignment | ||
|
||
In Rust, about the best we can do is an inconsistent alignment with one of the | ||
following two options: | ||
|
||
```rust | ||
use E::*; | ||
|
||
enum E { A, B, C, D } | ||
|
||
match foo { | ||
// | | ||
// V Inconsistently missing a `|`. | ||
A | ||
| B | ||
| C | ||
| D => (), | ||
} | ||
|
||
match foo { | ||
A | | ||
B | | ||
C | | ||
D => (), | ||
// ^ Also inconsistent but since this is the last in the sequence, not having | ||
// | a followup vert could be considered sensible given that no more follow. | ||
} | ||
``` | ||
|
||
This proposal would allow the example to have the following form: | ||
|
||
```rust | ||
use E::*; | ||
|
||
enum E { A, B, C, D } | ||
|
||
match foo { | ||
| A | ||
| B | ||
| C | ||
| D => (), | ||
// ^ Gained consistency by having a matching vert. | ||
} | ||
``` | ||
|
||
## Flexibility in single line matches | ||
|
||
It would allow these examples which are all equivalent: | ||
|
||
```rust | ||
use E::*; | ||
|
||
enum E { A, B, C, D } | ||
|
||
// A preceding vert | ||
match foo { | ||
| A | B | C | D => (), | ||
} | ||
|
||
// A match as is currently allowed | ||
match foo { | ||
A | B | C | D => (), | ||
} | ||
``` | ||
|
||
> There should be no ambiguity about what either of these means. Preference | ||
between these should just come down to a choice of style. | ||
|
||
## Benefits to macros | ||
|
||
This benefits macros. Needs filling in. | ||
|
||
## Multiple branches | ||
|
||
All of these matches are equivalent, each written in a different style: | ||
|
||
```rust | ||
use E::*; | ||
|
||
enum E { A, B, C, D } | ||
|
||
match foo { | ||
A | B => println!("Give me A | B!"), | ||
C | D => println!("Give me C | D!"), | ||
} | ||
|
||
match foo { | ||
| A | B => println!("Give me A | B!"), | ||
| C | D => println!("Give me C | D!"), | ||
} | ||
|
||
match foo { | ||
| A | ||
| B => println!("Give me A | B!"), | ||
| C | ||
| D => println!("Give me C | D!"), | ||
} | ||
|
||
match foo { | ||
A | B => | ||
println!("Give me A | B!"), | ||
C | D => | ||
println!("Give me C | D!"), | ||
} | ||
``` | ||
|
||
## Comparing misalignment | ||
|
||
```rust | ||
use E::*; | ||
|
||
enum E { A, B, C } | ||
|
||
match foo { | ||
| A | ||
| B => {}, | ||
| C => {} | ||
// ^ Following the style above, a `|` could be placed before the first | ||
// element of every branch. | ||
|
||
match value { | ||
| A | ||
| B => {}, | ||
C => {} | ||
// ^ Including a `|` for the `A` but not for the `C` seems inconsistent | ||
// but hardly invalid. Branches *always* follow the `=>`. Not something | ||
// a *grammar* should be greatly concerned about. | ||
} | ||
``` | ||
|
||
# Detailed design | ||
[design]: #detailed-design | ||
|
||
I don't know about the implementation but the grammar could be updated so that | ||
an optional `|` is allowed at the beginning and the end. Nothing else in the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The trailing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
grammar should need updating. | ||
|
||
```text | ||
// Before | ||
match_pat : pat [ '|' pat ] * [ "if" expr ] ? ; | ||
// After | ||
match_pat : '|' ? pat [ '|' pat ] * [ "if" expr ] ? ; | ||
``` | ||
|
||
# How We Teach This | ||
[how-we-teach-this]: #how-we-teach-this | ||
|
||
Adding examples for this are straightforward. You just include an example pointing | ||
out that leading verts are allowed. Simple examples such as below should be easy | ||
to add to all different resources. | ||
|
||
```rust | ||
use Letter::*; | ||
|
||
enum Letter { | ||
A, | ||
B, | ||
C, | ||
D, | ||
} | ||
|
||
fn main() { | ||
let a = Letter::A; | ||
let b = Letter::B; | ||
let c = Letter::C; | ||
let d = Letter::D; | ||
|
||
match a { | ||
A => "A", | ||
// Can do alternatives with a `|`. | ||
B | C | D => "B, C, or D", | ||
} | ||
|
||
match b { | ||
| A => "A", | ||
// Leading `|` is allowed. | ||
| B | ||
| C | ||
| D => "B, C, or D", | ||
} | ||
} | ||
``` | ||
|
||
# Drawbacks | ||
[drawbacks]: #drawbacks | ||
|
||
N/A | ||
|
||
# Alternatives | ||
[alternatives]: #alternatives | ||
|
||
N/A | ||
|
||
# Unresolved questions | ||
[unresolved]: #unresolved-questions | ||
|
||
N/A |
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.
Looks like the trailing backquote charactor is lost.
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.
Fixed