-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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: add documentation for book #41857
Changes from 2 commits
52c3380
7d94b48
7488ff5
3f980be
7ab35b7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,86 @@ The tracking issue for this feature is: [#37339] | |
|
||
[#37339]: https://github.com/rust-lang/rust/issues/37339 | ||
|
||
Documentation to be appended to section G of the book. | ||
|
||
------------------------ | ||
|
||
### Loops as expressions | ||
|
||
Like most things in Rust, loops are expressions; for example, the following is perfectly legal, | ||
if rather useless: | ||
|
||
```rust | ||
let result = for n in 1..4 { | ||
println!("Hello, {}", n); | ||
}; | ||
assert_eq!(result, ()); | ||
``` | ||
|
||
Until now, all the loops you have seen evaluate to either `()` or `!`, the latter being special | ||
syntax for "no value", meaning the loop never exits. A `loop` can instead evaluate to | ||
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. I don't find the |
||
a useful value via *break with value*: | ||
|
||
```rust | ||
// Find the first square number over 1000: | ||
let mut n = 1; | ||
let square = loop { | ||
if n * n > 1000 { | ||
break n * n; | ||
} | ||
n += 1; | ||
}; | ||
``` | ||
|
||
The evaluation type may be specified externally: | ||
|
||
```rust | ||
// Declare that value returned is unsigned 64-bit: | ||
let n: u64 = loop { | ||
break 1; | ||
}; | ||
``` | ||
|
||
It is an error if types do not agree, either between a "break" value and an external requirement, | ||
or between multiple "break" values: | ||
|
||
```rust | ||
loop { | ||
if random_bool() { | ||
break 1u32; | ||
} else { | ||
break 0u8; // error: types do not agree | ||
} | ||
}; | ||
|
||
let n: i32 = loop { | ||
break 0u32; // error: type does not agree with external requirement | ||
}; | ||
``` | ||
|
||
For now, breaking with a value is only possible with `loop`; the same functionality may | ||
some day be added to `for` and `while` (this would require some new syntax like | ||
`while f() { break 1; } default { break 0; }`). | ||
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. I don't like that this speculates about future language extensions and their syntax. 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. I half agree with you here, but I think that if there is no mention of the discrepancy between I suppose I could just omit the last bit about why 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 Rust book already uses loop to refer to all three repetitive control-flow constructs:
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. Your concerns are valid, but the why response is complex and depends on who you ask, imo it's too opinionated to get into that here. I definitely think your use of the loop term is correct, I just worry it may be confusing in this context. 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. Yeah; we don't say stuff like this in the docs because it often bitrots; then people think you can't do it when you actually can! |
||
|
||
#### Break: label, value | ||
|
||
Four forms of `break` are available, where EXPR is some expression which evaluates to a value: | ||
|
||
1. `break;` | ||
2. `break 'label;` | ||
3. `break EXPR;` | ||
4. `break 'label EXPR;` | ||
|
||
When no value is given, the value `()` is assumed, thus `break;` is equivalent to `break ();`. | ||
|
||
Using a label allows returning a value from an inner loop: | ||
|
||
```rust | ||
let result = 'outer: loop { | ||
for n in 1..10 { | ||
if n > 4 { | ||
break 'outer n; | ||
} | ||
} | ||
}; | ||
``` |
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 don't find this example very helpful in understanding the feature. The return value of
for
is a nice curiousity but I don't see much didatic value to this.