Skip to content

Commit d924309

Browse files
authored
Merge pull request #56 from dhardy/feature/loop_break_value
Feature/loop break value
2 parents dc5fe39 + 1eac99e commit d924309

File tree

1 file changed

+110
-50
lines changed

1 file changed

+110
-50
lines changed

src/expressions.md

+110-50
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ Significantly, lambda expressions _capture their environment_, which regular
643643
[function definitions](items.html#functions) do not. The exact type of capture
644644
depends on the [function type](types.html#function-types) inferred for the
645645
lambda expression. In the simplest and least-expensive form (analogous to a
646-
```|| { }``` expression), the lambda expression captures its environment by
646+
`|| { }` expression), the lambda expression captures its environment by
647647
reference, effectively borrowing pointers to all outer variables mentioned
648648
inside the function. Alternately, the compiler may infer that a lambda
649649
expression should copy or move values (depending on their type) from the
@@ -668,39 +668,32 @@ let word = "konnichiwa".to_owned();
668668
ten_times(move |j| println!("{}, {}", word, j));
669669
```
670670

671-
## Infinite loops
671+
## Loops
672672

673-
A `loop` expression denotes an infinite loop.
673+
Rust supports three loop expressions:
674674

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

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

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

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

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

701-
A `continue` expression is only permitted in the body of a loop.
702-
703-
## `while` loops
696+
### Predicate loops
704697

705698
A `while` loop begins by evaluating the boolean loop conditional expression.
706699
If the loop conditional expression evaluates to `true`, the loop body block
@@ -718,45 +711,112 @@ while i < 10 {
718711
}
719712
```
720713

721-
Like `loop` expressions, `while` loops can be controlled with `break` or
722-
`continue`, and may optionally have a _label_. See [infinite
723-
loops](#infinite-loops), [break expressions](#break-expressions), and
724-
[continue expressions](#continue-expressions) for more information.
725-
726-
## `for` expressions
714+
### Iterator loops
727715

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

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

733724
```rust
734-
# type Foo = i32;
735-
# fn bar(f: &Foo) { }
736-
# let a = 0;
737-
# let b = 0;
738-
# let c = 0;
739-
740-
let v: &[Foo] = &[a, b, c];
725+
let v = &["apples", "cake", "coffee"];
741726

742-
for e in v {
743-
bar(e);
727+
for text in v {
728+
println!("I like {}.", text);
744729
}
745730
```
746731

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

749734
```rust
750-
# fn bar(b:usize) { }
751-
for i in 0..256 {
752-
bar(i);
735+
let mut sum = 0;
736+
for n in 1..11 {
737+
sum += n;
738+
}
739+
assert_eq!(sum, 55);
740+
```
741+
742+
### Loop labels
743+
744+
A loop expression may optionally have a _label_. The label is written as
745+
a lifetime preceding the loop expression, as in `'foo: loop { break 'foo; }`,
746+
`'bar: while false {}`, `'humbug: for _ in 0..0 {}`.
747+
If a label is present, then labeled `break` and `continue` expressions nested
748+
within this loop may exit out of this loop or return control to its head.
749+
See [break expressions](#break-expressions) and [continue
750+
expressions](#continue-expressions).
751+
752+
### `break` expressions
753+
754+
When `break` is encountered, execution of the associated loop body is
755+
immediately terminated, for example:
756+
757+
```rust
758+
let mut last = 0;
759+
for x in 1..100 {
760+
if x > 12 {
761+
break;
762+
}
763+
last = x;
753764
}
765+
assert_eq!(last, 12);
766+
```
767+
768+
A `break` expression is normally associated with the innermost `loop`, `for` or
769+
`while` loop enclosing the `break` expression, but a [label](#loop-labels) can
770+
be used to specify which enclosing loop is affected. Example:
771+
772+
```rust
773+
'outer: loop {
774+
while true {
775+
break 'outer;
776+
}
777+
}
778+
```
779+
780+
A `break` expression is only permitted in the body of a loop, and has one of
781+
the forms `break`, `break 'label` or ([see below](#break-and-loop-values))
782+
`break EXPR` or `break 'label EXPR`.
783+
784+
### `continue` expressions
785+
786+
When `continue` is encountered, the current iteration of the associated loop
787+
body is immediately terminated, returning control to the loop *head*. In
788+
the case of a `while` loop, the head is the conditional expression controlling
789+
the loop. In the case of a `for` loop, the head is the call-expression
790+
controlling the loop.
791+
792+
Like `break`, `continue` is normally associated with the innermost enclosing
793+
loop, but `continue 'label` may be used to specify the loop affected.
794+
A `continue` expression is only permitted in the body of a loop.
795+
796+
### `break` and loop values
797+
798+
When associated with a `loop`, a break expression may be used to return a value
799+
from that loop, via one of the forms `break EXPR` or `break 'label EXPR`, where
800+
`EXPR` is an expression whose result is returned from the `loop`. For example:
801+
802+
```rust
803+
let (mut a, mut b) = (1, 1);
804+
let result = loop {
805+
if b > 10 {
806+
break b;
807+
}
808+
let c = a + b;
809+
a = b;
810+
b = c;
811+
};
812+
// first number in Fibonacci sequence over 10:
813+
assert_eq!(result, 13);
754814
```
755815

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

761821
## `if` expressions
762822

0 commit comments

Comments
 (0)