Skip to content

Commit 1101033

Browse files
committed
Revise whole section on loops to improve structure and progression.
1 parent f8dfbdc commit 1101033

File tree

1 file changed

+110
-62
lines changed

1 file changed

+110
-62
lines changed

src/expressions.md

+110-62
Original file line numberDiff line numberDiff line change
@@ -589,52 +589,32 @@ let word = "konnichiwa".to_owned();
589589
ten_times(move |j| println!("{}, {}", word, j));
590590
```
591591

592-
## Infinite loops
592+
## Loops
593593

594-
A `loop` expression denotes an infinite loop.
594+
Rust supports three loop expressions:
595595

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

603-
A `loop` expression is [diverging](items.html#diverging-functions), and doesn't
604-
return anything. However, when it contains a [break
605-
expression](#break-expressions), it returns the value attached to the `break`
606-
that caused the loop to stop.
601+
All three types of loop support [`break` expressions](#break-expressions),
602+
[`continue` expressions](#continue-expressions), and [labels](#loop-labels).
603+
Only `loop` supports [break-with-value](#break-with-value).
607604

608-
## `break` expressions
605+
### Infinite loops
609606

610-
A `break` expression has an optional _label_. If the label is absent, then
611-
executing a `break` expression immediately terminates the innermost loop
612-
enclosing it. It is only permitted in the body of a loop. If the label is
613-
present, then `break 'foo` terminates the loop with label `'foo`, which need not
614-
be the innermost label enclosing the `break` expression, but must enclose it.
607+
A `loop` expression repeats execution of its body continuously:
608+
`loop { println!("I live."); }`.
615609

616-
When the `break` expression is enclosed in a `loop` it has an optional return
617-
value attached which will be returned by the loop ended by the
618-
expression. When it's not provided it defaults to `()`.
610+
A `loop` expression without an associated `break` expression is
611+
[diverging](items.html#diverging-functions), and doesn't
612+
return anything. A `loop` expression containing associated
613+
[`break` expression(s)](#break-expressions)
614+
may terminate, and must have type compatible with the value of the `break`
615+
expression(s).
619616

620-
If both a label and a return value are present in the expression, the label
621-
must be placed before the return value. For example `break 'label 42` breaks
622-
the loop labelled `'label`, returning `42` from it.
623-
624-
## `continue` expressions
625-
626-
A `continue` expression has an optional _label_. If the label is absent, then
627-
executing a `continue` expression immediately terminates the current iteration
628-
of the innermost loop enclosing it, returning control to the loop *head*. In
629-
the case of a `while` loop, the head is the conditional expression controlling
630-
the loop. In the case of a `for` loop, the head is the call-expression
631-
controlling the loop. If the label is present, then `continue 'foo` returns
632-
control to the head of the loop with label `'foo`, which need not be the
633-
innermost label enclosing the `continue` expression, but must enclose it.
634-
635-
A `continue` expression is only permitted in the body of a loop.
636-
637-
## `while` loops
617+
### Predicate loops
638618

639619
A `while` loop begins by evaluating the boolean loop conditional expression.
640620
If the loop conditional expression evaluates to `true`, the loop body block
@@ -652,45 +632,113 @@ while i < 10 {
652632
}
653633
```
654634

655-
Like `loop` expressions, `while` loops can be controlled with `break` or
656-
`continue`, and may optionally have a _label_. See [infinite
657-
loops](#infinite-loops), [break expressions](#break-expressions), and
658-
[continue expressions](#continue-expressions) for more information.
659-
660-
## `for` expressions
635+
### Iterator loops
661636

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

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

667645
```rust
668-
# type Foo = i32;
669-
# fn bar(f: &Foo) { }
670-
# let a = 0;
671-
# let b = 0;
672-
# let c = 0;
646+
let v = &["apples", "cake", "coffee"];
673647

674-
let v: &[Foo] = &[a, b, c];
675-
676-
for e in v {
677-
bar(e);
648+
for text in v {
649+
println!("I like {}.", text);
678650
}
679651
```
680652

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

683655
```rust
684-
# fn bar(b:usize) { }
685-
for i in 0..256 {
686-
bar(i);
656+
let mut sum = 0;
657+
for n in 1..11 {
658+
sum += n;
659+
}
660+
assert_eq!(sum, 55);
661+
```
662+
663+
### Loop labels
664+
665+
A loop expression may optionally have a _label_. The label is written as
666+
a lifetime preceding the loop expression, as in `'foo: loop { break 'foo; }`,
667+
`'bar: while false {}`, `'humbug: for _ in 0..0 {}`.
668+
If a label is present, then labeled `break` and `continue` expressions nested
669+
within this loop may exit out of this loop or return control to its head.
670+
See [break expressions](#break-expressions) and [continue
671+
expressions](#continue-expressions).
672+
673+
### `break` expressions
674+
675+
When `break` is encountered, execution of the associated loop body is
676+
immediately terminated, for example:
677+
678+
```rust
679+
let mut last = 0;
680+
for x in 1..100 {
681+
if x > 12 {
682+
break;
683+
}
684+
last = x;
687685
}
686+
assert_eq!(last, 12);
687+
```
688+
689+
A `break` expression is normally associated with the innermost `loop`, `for` or
690+
`while` loop enclosing the `break` expression, but a [label](#loop-labels) can
691+
be used to specify which enclosing loop is affected. Example:
692+
693+
```rust
694+
'outer: loop {
695+
while true {
696+
break 'outer;
697+
}
698+
}
699+
```
700+
701+
A `break` expression is only permitted in the body of a loop, and has one of
702+
the forms `break`, `break 'label` or (see [break-with-value](#break-with-value))
703+
`break EXPR` or `break 'label EXPR`.
704+
705+
### `continue` expressions
706+
707+
When `continue` is encountered, the current iteration of the associated loop
708+
body is immediately terminated, returning control to the loop *head*. In
709+
the case of a `while` loop, the head is the conditional expression controlling
710+
the loop. In the case of a `for` loop, the head is the call-expression
711+
controlling the loop.
712+
713+
Like `break`, `continue` is normally associated with the innermost enclosing
714+
loop, but `continue 'label` may be used to specify the loop affected.
715+
A `continue` expression is only permitted in the body of a loop.
716+
717+
### Break-with-value
718+
719+
When associated with a `loop`, a break expression may be used to return a value
720+
from that loop, via one of the forms `break EXPR` or `break 'label EXPR`, where
721+
`EXPR` is an expression whose result is returned from the `loop`. For example:
722+
723+
```rust
724+
#![feature(loop_break_value)]
725+
let (mut a, mut b) = (1, 1);
726+
let result = loop {
727+
if b > 10 {
728+
break b;
729+
}
730+
let c = a + b;
731+
a = b;
732+
b = c;
733+
};
734+
// first number in Fibonacci sequence over 10:
735+
assert_eq!(result, 13);
688736
```
689737

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

695743
## `if` expressions
696744

0 commit comments

Comments
 (0)