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

loop-break-value (issue #961) #1624

Merged
merged 14 commits into from
Oct 22, 2016
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add discussion of for/while/while let
  • Loading branch information
dhardy committed May 26, 2016
commit 32bdf90b8266c2c50ec3e79c6c8e87d95fb22028
72 changes: 58 additions & 14 deletions text/0000-loop-break-value.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,16 +218,50 @@ otherwise and allows more flexibility in code layout.
# Unresolved questions
[unresolved]: #unresolved-questions

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

It should be noted that `for`, `while` and `while let` can all be emulated via
`loop`, so perhaps allowing the former to return values is less important.
Alternatively, a keyword such as `else default` could be used to
specify the other exit value as in:
A frequently discussed issue is extension of this concept to allow `for`,
`while` and `while let` expressions to return values in a similar way. There is
however a complication: these expressions may also terminate "naturally" (not
via break), and no consensus has been reached on how the result value should
be determined in this case, or even the result type.

There are three options:

1. Do not adjust `for`, `while` or `while let` at this time
2. Adjust these control structures to return an `Option<T>`, returning `None`
in the default case
3. Specify the default return value via some extra syntax

#### Via `Option<T>`

Unfortunately, option (2) is not possible to implement cleanly without breaking
a lot of existing code: many functions use one of these control structures in
tail position, where the current "value" of the expression, `()`, is implicitly
used:

```rust
// function returns `()`
fn print_my_values(v: &Vec<i32>) {
for x in v {
println!("Value: {}", x);
}
// loop exits with `()` which is implicitly "returned" from the function
}
```

Two variations of option (2) are possible:

* Only adjust the control structures where they contain a `break EXPR;` or
`break 'label EXPR;` statement. This may work but would necessitate that
`break;` and `break ();` mean different things.
* As a special case, make `break ();` return `()` instead of `Some(())`,
while for other values `break x;` returns `Some(x)`.

#### Via extra syntax for the default value

Several syntaxes have been proposed for how a control structure's default value
is set. For example:

```rust
fn first<T: Copy>(list: Iterator<T>) -> Option<T> {
Expand All @@ -239,8 +273,18 @@ fn first<T: Copy>(list: Iterator<T>) -> Option<T> {
}
```

The exact syntax is disputed; (JelteF has some suggestions which should work
without infinite parser lookahead)
[https://github.com/rust-lang/rfcs/issues/961#issuecomment-220728894].
It is suggested that this RFC should not be blocked on this issue since
loop-break-value can still be implemented in the manner above after this RFC.
or:

```rust
let x = for thing in things default "nope" {
if thing.valid() { break "found it!"; }
}
```

There are two things to bear in mind when considering new syntax:

* It is undesirable to add a new keyword to the list of Rust's keywords
* It is strongly desirable that unbounded lookahead is required while syntax
parsing Rust code

For more discussion on this topic, see [issue #961](https://github.com/rust-lang/rfcs/issues/961).