Skip to content

Commit 7739d40

Browse files
committed
rfc, if_while_or_patterns: expanded motivation + fixed formatting
1 parent f9179b8 commit 7739d40

File tree

1 file changed

+80
-11
lines changed

1 file changed

+80
-11
lines changed

text/0000-if-while-or-patterns.md

+80-11
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
# Summary
77
[summary]: #summary
88

9-
Enables "or" patterns for [`if let`](https://github.com/rust-lang/rfcs/pull/160) and [`while let`](https://github.com/rust-lang/rfcs/pull/214) expressions. In other words, examples like the following are now possible:
9+
[`if let`]: https://github.com/rust-lang/rfcs/pull/160
10+
[`while let`]: https://github.com/rust-lang/rfcs/pull/214
11+
12+
Enables "or" patterns for [`if let`] and [`while let`] expressions. In other
13+
words, examples like the following are now possible:
1014

1115
```rust
1216
enum E<T> {
@@ -27,7 +31,12 @@ while let A(x) | B(x) = source() {
2731
# Motivation
2832
[motivation]: #motivation
2933

30-
While nothing in this RFC is currently impossible in Rust, the changes the RFC proposes improves the ergonomics of control flow when dealing with `enum`s (sum types) with three or more variants where the program should react in one way to a group of variants, and another way to another group of variants. Examples of when such sum types occur are protocols and when dealing with languages (ASTs).
34+
While nothing in this RFC is currently impossible in Rust, the changes the RFC
35+
proposes improves the ergonomics of control flow when dealing with `enum`s
36+
(sum types) with three or more variants where the program should react in one
37+
way to a group of variants, and another way to another group of variants.
38+
Examples of when such sum types occur are protocols, when dealing with
39+
languages (ASTs), and non-trivial iterators.
3140

3241
The following snippet (written with this RFC):
3342

@@ -56,7 +65,51 @@ match expr {
5665
}
5766
```
5867

59-
With `while let`, the ergonomics and in particular the readability can be significantly improved.
68+
[`std::iter`]: https://doc.rust-lang.org/nightly/src/core/iter/mod.rs.html#691
69+
70+
This way of using `match` is seen multiple times in [`std::iter`] when dealing
71+
with the `Chain` iterator adapter. An example of this is:
72+
73+
```rust
74+
fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
75+
where F: FnMut(Acc, Self::Item) -> Acc,
76+
{
77+
let mut accum = init;
78+
match self.state {
79+
ChainState::Both | ChainState::Front => {
80+
accum = self.a.fold(accum, &mut f);
81+
}
82+
_ => { }
83+
}
84+
match self.state {
85+
ChainState::Both | ChainState::Back => {
86+
accum = self.b.fold(accum, &mut f);
87+
}
88+
_ => { }
89+
}
90+
accum
91+
}
92+
```
93+
94+
which could have been written as:
95+
96+
```rust
97+
fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc
98+
where F: FnMut(Acc, Self::Item) -> Acc,
99+
{
100+
use ChainState::*;
101+
let mut accum = init;
102+
if let Both | Front = self.state { accum = self.a.fold(accum, &mut f); }
103+
if let Both | Back = self.state { accum = self.b.fold(accum, &mut f); }
104+
accum
105+
}
106+
```
107+
108+
This version is both shorter and clearer.
109+
110+
111+
With `while let`, the ergonomics and in particular the readability can be
112+
significantly improved.
60113

61114
The following snippet (written with this RFC):
62115

@@ -82,11 +135,18 @@ Another major motivation of the RFC is consistency with `match`.
82135
# Guide-level explanation
83136
[guide-level-explanation]: #guide-level-explanation
84137

85-
[RFC 2005](https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#examples), in describing the third example in the section "Examples", refers to patterns with `|` in them as "or" patterns. This RFC adopts the same terminology.
138+
[RFC 2005]: https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#examples
86139

87-
While the "sum" of all patterns in `match` must be irrefutable, or in other words: cover all cases, be exhaustive, this is not the case (currently) with `if/while let`, which may have a refutable pattern. This RFC does not change this.
140+
[RFC 2005], in describing the third example in the section "Examples", refers to
141+
patterns with `|` in them as "or" patterns. This RFC adopts the same terminology.
88142

89-
The RFC only extends the use of or-patterns from `match`es to `if let` and `while let` expressions.
143+
While the "sum" of all patterns in `match` must be irrefutable, or in other
144+
words: cover all cases, be exhaustive, this is not the case (currently) with
145+
`if/while let`, which may have a refutable pattern.
146+
This RFC does not change this.
147+
148+
The RFC only extends the use of or-patterns from `match`es to `if let` and
149+
`while let` expressions.
90150

91151
For examples, see [motivation].
92152

@@ -95,9 +155,12 @@ For examples, see [motivation].
95155

96156
## Grammar
97157

158+
[§ 7.2.24]: https://doc.rust-lang.org/grammar.html#if-let-expressions
159+
[§ 7.2.25]: https://doc.rust-lang.org/grammar.html#while-let-loops
160+
98161
### `if let`
99162

100-
The grammar in [§ 7.2.24](https://doc.rust-lang.org/grammar.html#if-let-expressions) is changed from:
163+
The grammar in [§ 7.2.24] is changed from:
101164

102165
```
103166
if_let_expr : "if" "let" pat '=' expr '{' block '}'
@@ -113,7 +176,7 @@ if_let_expr : "if" "let" pat [ '|' pat ] * '=' expr '{' block '}'
113176

114177
### `while let`
115178

116-
The grammar in [§ 7.2.25](https://doc.rust-lang.org/grammar.html#while-let-loops) is changed from:
179+
The grammar in [§ 7.2.25] is changed from:
117180

118181
```
119182
while_let_expr : [ lifetime ':' ] ? "while" "let" pat '=' expr '{' block '}' ;
@@ -127,11 +190,15 @@ while_let_expr : [ lifetime ':' ] ? "while" "let" pat [ '|' pat ] * '=' expr '{'
127190

128191
## Syntax lowering
129192

130-
The changes proposed in this RFC can be implemented by transforming the `if/while let` constructs with a syntax-lowering pass into `match` and `loop` + `match` expressions.
193+
The changes proposed in this RFC can be implemented by transforming the
194+
`if/while let` constructs with a syntax-lowering pass into `match` and
195+
`loop` + `match` expressions.
131196

132197
### Examples, `if let`
133198

134-
These examples are extensions on the [`if let` RFC](https://github.com/rust-lang/rfcs/pull/160). Therefore, the RFC avoids
199+
[`if let` RFC]: https://github.com/rust-lang/rfcs/pull/160
200+
201+
These examples are extensions on the [`if let` RFC]. Therefore, the RFC avoids
135202
duplicating any details already specified there.
136203

137204
Source:
@@ -202,7 +269,9 @@ match EXPR {
202269

203270
### Examples, `while let`
204271

205-
The following example is an extension on the [`while let` RFC](https://github.com/rust-lang/rfcs/pull/214).
272+
[`while let` RFC]: https://github.com/rust-lang/rfcs/pull/214
273+
274+
The following example is an extension on the [`while let` RFC].
206275

207276
Source
208277
```rust

0 commit comments

Comments
 (0)