Loop expressions - The Rust Reference

# Loops

> Syntax
> LoopExpression :
> LoopLabel? (
> InfiniteLoopExpression
> | PredicateLoopExpression
> | PredicatePatternLoopExpression
> | IteratorLoopExpression
> )

Rust supports four loop expressions:

- A `loop` expression denotes an infinite loop.
- A `while` expression loops until a predicate is false.
- A `while let` expression tests a refutable pattern.
- A `for` expression extracts values from an iterator, looping until the iterator is empty.

All four types of loop support `break` expressions, `continue` expressions, and labels. Only `loop` supports evaluation to non-trivial values.

## Infinite loops

> Syntax
> InfiniteLoopExpression :
> `loop` BlockExpression

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

A `loop` expression without an associated `break` expression is diverging, and doesn't return anything. A `loop` expression containing associated `break` expression(s) may terminate, and must have type compatible with the value of the `break` expression(s).

## Predicate loops

> Syntax
> PredicateLoopExpression :
> `while` Expressionexcept struct expression BlockExpression

A `while` loop begins by evaluating the boolean loop conditional expression. If the loop conditional expression evaluates to `true`, the loop body block executes, then control returns to the loop conditional expression. If the loop conditional expression evaluates to `false`, the `while` expression completes.

An example:

    # #![allow(unused_variables)]
    #fn main() {
    let mut i = 0;

    while i < 10 {
        println!("hello");
        i = i + 1;
    }
    #}

## Predicate pattern loops

> Syntax
> PredicatePatternLoopExpression :
> `while` `let` Pattern `=` Expressionexcept struct expression BlockExpression

A `while let` loop is semantically similar to a `while` loop but in place of a condition expression it expects the keyword `let` followed by a refutable pattern, an `=`, an expression and a block expression. If the value of the expression on the right hand side of the `=` matches the pattern, the loop body block executes then control returns to the pattern matching statement. Otherwise, the while expression completes.

    # #![allow(unused_variables)]
    #fn main() {
    let mut x = vec![1, 2, 3];

    while let Some(y) = x.pop() {
        println!("y = {}", y);
    }
    #}

## Iterator loops

> Syntax
> IteratorLoopExpression :
> `for` Pattern `in` Expressionexcept struct expression BlockExpression

A `for` expression is a syntactic construct for looping over elements provided 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:

    # #![allow(unused_variables)]
    #fn main() {
    let v = &["apples", "cake", "coffee"];

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

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

    # #![allow(unused_variables)]
    #fn main() {
    let mut sum = 0;
    for n in 1..11 {
        sum += n;
    }
    assert_eq!(sum, 55);
    #}

## Loop labels

> Syntax
> LoopLabel :
> LIFETIME_OR_LABEL `:`

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 and continue expressions.

## `break` expressions

> Syntax
> BreakExpression :
> `break` LIFETIME_OR_LABEL? Expression?

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

    # #![allow(unused_variables)]
    #fn main() {
    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 can be used to specify which enclosing loop is affected. Example:

    # #![allow(unused_variables)]
    #fn main() {
    '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 EXPR` or `break 'label EXPR`.

## `continue` expressions

> Syntax
> ContinueExpression :
> `continue` LIFETIME_OR_LABEL?

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:

    # #![allow(unused_variables)]
    #fn main() {
    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);
    #}

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 `()`.