Skip to content

Feature/loop break value #56

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

Merged
merged 4 commits into from
May 26, 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
160 changes: 110 additions & 50 deletions src/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ Significantly, lambda expressions _capture their environment_, which regular
[function definitions](items.html#functions) do not. The exact type of capture
depends on the [function type](types.html#function-types) inferred for the
lambda expression. In the simplest and least-expensive form (analogous to a
```|| { }``` expression), the lambda expression captures its environment by
`|| { }` expression), the lambda expression captures its environment by
reference, effectively borrowing pointers to all outer variables mentioned
inside the function. Alternately, the compiler may infer that a lambda
expression should copy or move values (depending on their type) from the
Expand All @@ -589,39 +589,32 @@ let word = "konnichiwa".to_owned();
ten_times(move |j| println!("{}, {}", word, j));
```

## Infinite loops
## Loops

A `loop` expression denotes an infinite loop.
Rust supports three loop expressions:

A `loop` expression may optionally have a _label_. The label is written as
a lifetime preceding the loop expression, as in `'foo: loop{ }`. If a
label is present, then labeled `break` and `continue` expressions nested
within this loop may exit out of this loop or return control to its head.
See [break expressions](#break-expressions) and [continue
expressions](#continue-expressions).
* A [`loop` expression](#infinite-loops) denotes an infinite loop.
* A [`while` expression](#predicate-loops) loops until a predicate is false.
* A [`for` expression](#iterator-loops) extracts values from an iterator,
looping until the iterator is empty.

## `break` expressions
All three types of loop support [`break` expressions](#break-expressions),
[`continue` expressions](#continue-expressions), and [labels](#loop-labels).
Only `loop` supports [evaluation to non-trivial values](#break-and-loop-values).

A `break` expression has an optional _label_. If the label is absent, then
executing a `break` expression immediately terminates the innermost loop
enclosing it. It is only permitted in the body of a loop. If the label is
present, then `break 'foo` terminates the loop with label `'foo`, which need not
be the innermost label enclosing the `break` expression, but must enclose it.
### Infinite loops

## `continue` expressions
A `loop` expression repeats execution of its body continuously:
`loop { println!("I live."); }`.

A `continue` expression has an optional _label_. If the label is absent, then
executing a `continue` expression immediately terminates the current iteration
of the innermost loop enclosing it, returning control to the loop *head*. In
the case of a `while` loop, the head is the conditional expression controlling
the loop. In the case of a `for` loop, the head is the call-expression
controlling the loop. If the label is present, then `continue 'foo` returns
control to the head of the loop with label `'foo`, which need not be the
innermost label enclosing the `continue` expression, but must enclose it.
A `loop` expression without an associated `break` expression is
[diverging](items.html#diverging-functions), and doesn't
return anything. A `loop` expression containing associated
[`break` expression(s)](#break-expressions)
may terminate, and must have type compatible with the value of the `break`
expression(s).

A `continue` expression is only permitted in the body of a loop.

## `while` loops
### Predicate loops

A `while` loop begins by evaluating the boolean loop conditional expression.
If the loop conditional expression evaluates to `true`, the loop body block
Expand All @@ -639,45 +632,112 @@ while i < 10 {
}
```

Like `loop` expressions, `while` loops can be controlled with `break` or
`continue`, and may optionally have a _label_. See [infinite
loops](#infinite-loops), [break expressions](#break-expressions), and
[continue expressions](#continue-expressions) for more information.

## `for` expressions
### Iterator loops

A `for` expression is a syntactic construct for looping over elements provided
by an implementation of `std::iter::IntoIterator`.
by an implementation of `std::iter::IntoIterator`. If the iterator yields a
value, that value is given the specified name and the body of the loop is
executed, then control returns to the head of the `for` loop. If the iterator
is empty, the `for` expression completes.

An example of a `for` loop over the contents of an array:

```rust
# type Foo = i32;
# fn bar(f: &Foo) { }
# let a = 0;
# let b = 0;
# let c = 0;

let v: &[Foo] = &[a, b, c];
let v = &["apples", "cake", "coffee"];

for e in v {
bar(e);
for text in v {
println!("I like {}.", text);
}
```

An example of a for loop over a series of integers:

```rust
# fn bar(b:usize) { }
for i in 0..256 {
bar(i);
let mut sum = 0;
for n in 1..11 {
sum += n;
}
assert_eq!(sum, 55);
```

### Loop labels

A loop expression may optionally have a _label_. The label is written as
a lifetime preceding the loop expression, as in `'foo: loop { break 'foo; }`,
`'bar: while false {}`, `'humbug: for _ in 0..0 {}`.
If a label is present, then labeled `break` and `continue` expressions nested
within this loop may exit out of this loop or return control to its head.
See [break expressions](#break-expressions) and [continue
expressions](#continue-expressions).

### `break` expressions

When `break` is encountered, execution of the associated loop body is
immediately terminated, for example:

```rust
let mut last = 0;
for x in 1..100 {
if x > 12 {
break;
}
last = x;
}
assert_eq!(last, 12);
```

A `break` expression is normally associated with the innermost `loop`, `for` or
`while` loop enclosing the `break` expression, but a [label](#loop-labels) can
be used to specify which enclosing loop is affected. Example:

```rust
'outer: loop {
while true {
break 'outer;
}
}
```

A `break` expression is only permitted in the body of a loop, and has one of
the forms `break`, `break 'label` or ([see below](#break-and-loop-values))
`break EXPR` or `break 'label EXPR`.

### `continue` expressions

When `continue` is encountered, the current iteration of the associated loop
body is immediately terminated, returning control to the loop *head*. In
the case of a `while` loop, the head is the conditional expression controlling
the loop. In the case of a `for` loop, the head is the call-expression
controlling the loop.

Like `break`, `continue` is normally associated with the innermost enclosing
loop, but `continue 'label` may be used to specify the loop affected.
A `continue` expression is only permitted in the body of a loop.

### `break` and loop values

When associated with a `loop`, a break expression may be used to return a value
from that loop, via one of the forms `break EXPR` or `break 'label EXPR`, where
`EXPR` is an expression whose result is returned from the `loop`. For example:

```rust
let (mut a, mut b) = (1, 1);
let result = loop {
if b > 10 {
break b;
}
let c = a + b;
a = b;
b = c;
};
// first number in Fibonacci sequence over 10:
assert_eq!(result, 13);
```

Like `loop` expressions, `for` loops can be controlled with `break` or
`continue`, and may optionally have a _label_. See [infinite
loops](#infinite-loops), [break expressions](#break-expressions), and
[continue expressions](#continue-expressions) for more information.
In the case a `loop` has an associated `break`, it is not considered diverging,
and the `loop` must have a type compatible with each `break` expression.
`break` without an expression is considered identical to `break` with
expression `()`.

## `if` expressions

Expand Down