Skip to content

Commit 32bdf90

Browse files
committed
Add discussion of for/while/while let
1 parent d6e1594 commit 32bdf90

File tree

1 file changed

+58
-14
lines changed

1 file changed

+58
-14
lines changed

text/0000-loop-break-value.md

+58-14
Original file line numberDiff line numberDiff line change
@@ -218,16 +218,50 @@ otherwise and allows more flexibility in code layout.
218218
# Unresolved questions
219219
[unresolved]: #unresolved-questions
220220

221-
It would be possible to allow `for`, `while` and `while let` expressions return
222-
values in a similar way; however, these expressions may also terminate
223-
"naturally" (not via break), and no consensus has been reached on how the
224-
result value should be determined in this case, or even the result type.
225-
It is thus proposed not to change these expressions at this time.
221+
### Extension to for, while, while let
226222

227-
It should be noted that `for`, `while` and `while let` can all be emulated via
228-
`loop`, so perhaps allowing the former to return values is less important.
229-
Alternatively, a keyword such as `else default` could be used to
230-
specify the other exit value as in:
223+
A frequently discussed issue is extension of this concept to allow `for`,
224+
`while` and `while let` expressions to return values in a similar way. There is
225+
however a complication: these expressions may also terminate "naturally" (not
226+
via break), and no consensus has been reached on how the result value should
227+
be determined in this case, or even the result type.
228+
229+
There are three options:
230+
231+
1. Do not adjust `for`, `while` or `while let` at this time
232+
2. Adjust these control structures to return an `Option<T>`, returning `None`
233+
in the default case
234+
3. Specify the default return value via some extra syntax
235+
236+
#### Via `Option<T>`
237+
238+
Unfortunately, option (2) is not possible to implement cleanly without breaking
239+
a lot of existing code: many functions use one of these control structures in
240+
tail position, where the current "value" of the expression, `()`, is implicitly
241+
used:
242+
243+
```rust
244+
// function returns `()`
245+
fn print_my_values(v: &Vec<i32>) {
246+
for x in v {
247+
println!("Value: {}", x);
248+
}
249+
// loop exits with `()` which is implicitly "returned" from the function
250+
}
251+
```
252+
253+
Two variations of option (2) are possible:
254+
255+
* Only adjust the control structures where they contain a `break EXPR;` or
256+
`break 'label EXPR;` statement. This may work but would necessitate that
257+
`break;` and `break ();` mean different things.
258+
* As a special case, make `break ();` return `()` instead of `Some(())`,
259+
while for other values `break x;` returns `Some(x)`.
260+
261+
#### Via extra syntax for the default value
262+
263+
Several syntaxes have been proposed for how a control structure's default value
264+
is set. For example:
231265

232266
```rust
233267
fn first<T: Copy>(list: Iterator<T>) -> Option<T> {
@@ -239,8 +273,18 @@ fn first<T: Copy>(list: Iterator<T>) -> Option<T> {
239273
}
240274
```
241275

242-
The exact syntax is disputed; (JelteF has some suggestions which should work
243-
without infinite parser lookahead)
244-
[https://github.com/rust-lang/rfcs/issues/961#issuecomment-220728894].
245-
It is suggested that this RFC should not be blocked on this issue since
246-
loop-break-value can still be implemented in the manner above after this RFC.
276+
or:
277+
278+
```rust
279+
let x = for thing in things default "nope" {
280+
if thing.valid() { break "found it!"; }
281+
}
282+
```
283+
284+
There are two things to bear in mind when considering new syntax:
285+
286+
* It is undesirable to add a new keyword to the list of Rust's keywords
287+
* It is strongly desirable that unbounded lookahead is required while syntax
288+
parsing Rust code
289+
290+
For more discussion on this topic, see [issue #961](https://github.com/rust-lang/rfcs/issues/961).

0 commit comments

Comments
 (0)