Sling Academy
Home/Rust/Iterator-Based `for` Loops in Rust: `for x in 0..n`

Iterator-Based `for` Loops in Rust: `for x in 0..n`

Last updated: January 03, 2025

Rust is a modern systems programming language that leans heavily on concise syntax to improve code readability and developer productivity. One of the features Rust developers appreciate is the iterator-based for loop, which is encapsulated with the syntax for x in 0..n. This construct provides an elegant way to iterate over a range of values, making it a preferred choice for many Rust programmers.

Understanding Ranges and Iterators

In Rust, a range is defined using the start..end syntax, which includes numbers starting from start up to (but not including) end. You can think of it as a shorthand for creating a sequence of steps over you wish to iterate.

Here is a simple code example of using a range in a for loop:


fn main() {
    for x in 0..5 {
        println!("{}", x);
    }
}

In this example, the loop will run with x taking values from 0 to 4. The value 5 is excluded from the iteration.

Inclusive Ranges

To include the end value in the iteration, Rust offers an alternative syntax using two dots and an equal sign, ..=:


fn main() {
    for x in 0..=5 {
        println!("{}", x);
    }
}

This loop will print numbers 0 through 5, as the 5 is included in the range.

Iterating Over Collections

Rust’s for loop is not limited to numeric ranges; you can iterate over any type that implements the IntoIterator trait, such as arrays, vectors, and other collections.


fn main() {
    let fruits = vec!["apple", "banana", "cherry"];
    for fruit in &fruits {
        println!("{}", fruit);
    }
}

Here, the for loop iterates over each element in the fruits vector, printing each fruit’s name. The & symbol is used to pass a reference, allowing fruits to remain unmodified after the loop.

Advanced Iterations

Sometimes you might want to have more control over the loop iteration, such as modifying the iterable as you iterate over it, filtering, or transforming items. Using iterators directly provides this functionality.


fn main() {
    let numbers = vec![1, 2, 3, 4, 5];
    let squares: Vec = numbers.iter()
                                   .map(|x| x * x)
                                   .collect();

    for sq in squares {
        println!("{}", sq);
    }
}

In this example, the iterator is used directly to create a new vector containing the squares of the original numbers. The .iter() method creates an iterator over the vector, .map() applies a function to each element, and .collect() gathers the results into a new vector.

Conclusion

The iterator-based for loop in Rust elegantly handles both simple and complex iteration tasks. Ranges provide a straightforward means of iterating over sequences of numbers, while the ability to iterate over collections provides flexibility and convenience. Overall, Rust’s iteration constructs help developers express iteration logic succinctly and clearly, enhancing both the readability and maintainability of code.

Next Article: Destructuring in `for` Loops: Pattern Matching Each Element in Rust

Previous Article: Managing Loop State with Mutable Variables in Rust

Series: Control Flow in Rust

Rust

You May Also Like

  • E0557 in Rust: Feature Has Been Removed or Is Unavailable in the Stable Channel
  • Network Protocol Handling Concurrency in Rust with async/await
  • Using the anyhow and thiserror Crates for Better Rust Error Tests
  • Rust - Investigating partial moves when pattern matching on vector or HashMap elements
  • Rust - Handling nested or hierarchical HashMaps for complex data relationships
  • Rust - Combining multiple HashMaps by merging keys and values
  • Composing Functionality in Rust Through Multiple Trait Bounds
  • E0437 in Rust: Unexpected `#` in macro invocation or attribute
  • Integrating I/O and Networking in Rust’s Async Concurrency
  • E0178 in Rust: Conflicting implementations of the same trait for a type
  • Utilizing a Reactor Pattern in Rust for Event-Driven Architectures
  • Parallelizing CPU-Intensive Work with Rust’s rayon Crate
  • Managing WebSocket Connections in Rust for Real-Time Apps
  • Downloading Files in Rust via HTTP for CLI Tools
  • Mocking Network Calls in Rust Tests with the surf or reqwest Crates
  • Rust - Designing advanced concurrency abstractions using generic channels or locks
  • Managing code expansion in debug builds with heavy usage of generics in Rust
  • Implementing parse-from-string logic for generic numeric types in Rust
  • Rust.- Refining trait bounds at implementation time for more specialized behavior