
Loops
Repeating things in Rust can be done using three constructs, namely loop, while, and for. In all of them, we have the usual continue and break keywords, which allow you to skip and break out of a loop, respectively. Here's an example of using loop, which is equivalent to C's while(true):
// loops.rs
fn main() {
let mut x = 1024;
loop {
if x < 0 {
break;
}
println!("{} more runs to go", x);
x -= 1;
}
}
loop represents an infinite loop. In the preceding code, we simply decrement the value x until it hits the if condition x < 0, where we break out of the loop. An extra feature of using loop in Rust is being able to tag the loop block with a name. This can be used in cases where you have two or more nested loops and want to break out from any one of them and not just the loop immediately enclosing the break statement. The following is an example of using loop labels to break out of the loop:
// loop_labels.rs
fn silly_sub(a: i32, b: i32) -> i32 {
let mut result = 0;
'increment: loop {
if result == a {
let mut dec = b;
'decrement: loop {
if dec == 0 {
// breaks directly out of 'increment loop
break 'increment;
} else {
result -= 1;
dec -= 1;
}
}
} else {
result += 1;
}
}
result
}
fn main() {
let a = 10;
let b = 4;
let result = silly_sub(a, b);
println!("{} minus {} is {}", a, b, result);
}
In the preceding code, we are doing a very inefficient subtraction just to demonstrate the usage of labels with nested loops. In the inner 'decrement label, when dec equals 0, we can pass a label to break (here, this is 'increment) and break out of the outer 'increment loop instead.
Now, let's take a look at while loops. Nothing fancy here:
// while.rs
fn main() {
let mut x = 1000;
while x > 0 {
println!("{} more runs to go", x);
x -= 1;
}
}
Rust also has a for keyword and is similar to for loops used in other languages, but they are quite different in their implementation. Rust's for is basically a syntax sugar for a more powerful repetition construct known as iterators. We'll discuss them in more detail in Chapter 7, Advanced Concepts. To put it simply, for loops in Rust only work on types that can be converted into iterators. One such type is the Range type. The Range type can refer to a range of numbers, such as (0..10). They can be used in for loops like so:
// for_loops.rs
fn main() {
// does not include 10
print!("Normal ranges: ");
for i in 0..10 {
print!("{},", i);
}
println!(); // just a newline
print!("Inclusive ranges: ");
// counts till 10
for i in 0..=10 {
print!("{},", i);
}
}
Apart from the normal range syntax, that is, 0..10, which does not include 10, Rust also has inclusive range syntax 0..=10, which iterates all the way until 10, as can be seen in the second for loop. Now, let's move on to user-defined data types.