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: add documentation for book #41857

Merged
merged 5 commits into from
May 17, 2017
Merged
Changes from all commits
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
73 changes: 73 additions & 0 deletions src/doc/unstable-book/src/language-features/loop-break-value.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,80 @@ 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, and have a value; normally `()` unless the loop
never exits.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, I think this is more to the point now. "unless the loop never exits" only applies to loop and not any loop that never exists (see how even we are getting confused by the terms), for and while always evaluate to (). But diverging things are very niche, maybe we should just not mention this here?

A `loop` can instead evaluate to a useful value via *break with value*:

```rust
#![feature(loop_break_value)]

// 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
#![feature(loop_break_value)]

// 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:

```no_compile
#![feature(loop_break_value)]

loop {
if true {
break 1u32;
} else {
break 0u8; // error: types do not agree
}
};

let n: i32 = loop {
break 0u32; // error: type does not agree with external requirement
};
```

#### 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
#![feature(loop_break_value)]

let result = 'outer: loop {
for n in 1..10 {
if n > 4 {
break 'outer n;
}
}
};
```