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 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 has type `!`. 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` MatchArmPatterns `=` 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 pattern, an `=`, a scrutinee expression and a block expression. If the value of the scrutinee 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);
    }

    while let _ = 5 {
        println!("Irrefutable patterns are always true");
        break;
    }
    }

A `while let` loop is equivalent to a `loop` expression containing a `match` expression as follows.

    'label: while let PATS = EXPR {
        /* loop body */
    }

is equivalent to

    'label: loop {
        match EXPR {
            PATS => { /* loop body */ },
            _ => break,
        }
    }

Multiple patterns may be specified with the `|` operator. This has the same semantics as with `|` in `match` expressions:

    #![allow(unused_variables)]
    fn main() {
    let mut vals = vec![2, 3, 1, 2, 2];
    while let Some(v @ 1) | Some(v @ 2) = vals.pop() {
        // Prints 2, 2, then 1
        println!("{}", v);
    }
    }

## 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 matched against the irrefutable pattern, the body of the loop is executed, and 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);
    }

A for loop is equivalent to the following block expression.

    'label: for PATTERN in iter_expr {
        /* loop body */
    }

is equivalent to

    {
        let result = match IntoIterator::into_iter(iter_expr) {
            mut iter => 'label: loop {
                let mut next;
                match Iterator::next(&mut iter) {
                    Option::Some(val) => next = val,
                    Option::None => break,
                };
                let PAT = next;
                let () = { /* loop body */ };
            },
        };
        result
    }

`IntoIterator`, `Iterator`, and `Option` are always the standard library items here, not whatever those names resolve to in the current scope. The variable names `next`, `iter`, and `val` are for exposition only, they do not actually have names the user can type.

> Note: that the outer `match` is used to ensure that any temporary values in `iter_expr` don't get dropped before the loop is finished. `next` is declared before being assigned because it results in types being inferred correctly more often.

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