Skip to content

Commit

Permalink
Guide: looping
Browse files Browse the repository at this point in the history
  • Loading branch information
steveklabnik committed Jul 8, 2014
1 parent 35e2134 commit 636aff1
Showing 1 changed file with 137 additions and 4 deletions.
141 changes: 137 additions & 4 deletions src/doc/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -958,13 +958,146 @@ Enums

## Looping

for
Looping is the last basic construct that we haven't learned yet in Rust. Rust has
two main looping constructs: `for` and `while`.

while
### `for`

loop
The `for` loop is used to loop a particular number of times. Rust's `for` loops
work a bit differently than in other systems languages, however. Rust's `for`
loop doesn't look like this C `for` loop:

break/continue
```{ignore,c}
for (x = 0; x < 10; x++) {

This comment has been minimized.

Copy link
@nielsle

nielsle Jul 11, 2014

This is slightly confusing for readers that do not know C or C++. As an alternative you could write. "Here is a program that prints the numbers from 0 to 9"

printf( "%d\n", x );
}
```

It looks like this:

```{rust}
for x in range(0i, 10i) {
println!("{:d}", x);
}
```

In slightly more abstract terms,

```{ignore,notrust}
for var in expression {
code
}
```

The expression is an iterator, which we will discuss in more depth later in the
guide. The iterator gives back a series of elements. Each element is one
iteration of the loop. That value is then bound to the name `var`, which is
valid for the loop body. Once the body is over, the next value is fetched from
the iterator, and we loop another time. When there are no more values, the
`for` loop is over.

In our example, the `range` function is a function, provided by Rust, that
takes a start and an end position, and gives an iterator over those values. The
upper bound is exclusive, though, so our loop will print `0` through `9`, not
`10`.

Rust does not have the "C style" `for` loop on purpose. Manually controlling
each element of the loop is complicated and error prone, even for experienced C
developers. There's an old joke that goes, "There are two hard problems in
computer science: naming things, cache invalidation, and off-by-one errors."
The joke, of course, being that the setup says "two hard problems" but then
lists three things. This happens quite a bit with "C style" `for` loops.

We'll talk more about `for` when we cover **vector**s, later in the Guide.

### `while`

The other kind of looping construct in Rust is the `while` loop. It looks like
this:

```{rust}

This comment has been minimized.

Copy link
@nielsle

nielsle Jul 11, 2014

If you aim at beginners then you may wish a simpler example here. One idea is to write the numbers from 9 to 0 in reverse.

This comment has been minimized.

Copy link
@steveklabnik

steveklabnik Jul 11, 2014

Author Owner

That would be better done as a for, I need something that explicitly needs a while.

This comment has been minimized.

Copy link
@nielsle

nielsle Jul 11, 2014

Good point. Rubys tutorial finds the smallest power of 2 that is greater than 10000.
http://www.ruby-doc.org/docs/Tutorial/part_02/while.html

let mut x = 5u;
let mut done = false;
while !done {
x += x - 3;
println!("{}", x);
if x % 5 == 0 { done = true; }
}
```

`while` loops are the correct choice when you're not sure how many times
you need to loop.

If you need an infinite loop, you may be tempted to write this:

```{rust,ignore}
while true {
```

Rust has a dedicated keyword, `loop`, to handle this case:

```{rust,ignore}
loop {
```

Rust's control-flow analysis treats this construct differently than a
`while true`, since we know that it will always loop. The details of what
that _means_ aren't super important to understand at this stage, but in
general, the more information we can give to the compiler, the better it
can do with safety and code generation. So you should always prefer
`loop` when you plan to loop infinitely.

### Ending iteration early

Let's take a look at that `while` loop we had earlier:

```{rust}

This comment has been minimized.

Copy link
@nielsle

nielsle Jul 11, 2014

Nice detail to repeat the example.

let mut x = 5u;
let mut done = false;
while !done {
x += x - 3;
println!("{}", x);
if x % 5 == 0 { done = true; }
}
```

We had to keep a dedicated `mut` boolean variable binding, `done`, to know
when we should skip out of the loop. Rust has two keywords to help us with
modifying iteration: `break` and `continue`.

In this case, we can write the loop in a better way with `break`:

```{rust}
let mut x = 5u;
loop {
x += x - 3;
println!("{}", x);
if x % 5 == 0 { break; }
}
```

We now loop forever with `loop`, and use `break` to break out early.

`continue` is similar, but instead of ending the loop, goes to the next
iteration: This will only print the odd numbers:

```
for x in range(0i, 10i) {
if x % 2 == 0 { continue; }
println!("{:d}", x);
}
```

Both `continue` and `break` are valid in both kinds of loops.

We have now learned all of the most basic Rust concepts. We're ready to start
building our guessing game, but we need to know how to do one last thing first:
get input from the keyboard. You can't have a guessing game without the ability
to guess!

## Guessing Game: complete

Expand Down

1 comment on commit 636aff1

@brson
Copy link

@brson brson commented on 636aff1 Jul 14, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r+

Please sign in to comment.