For loops decrement by more than 1 value

In C-like syntax if I wanted a for loop that went backwards and it decrements by 2 I could do this

for (int i = 10; i <= 0; i -= 2)
{
    // Does something
}

In rust, how do I do this?

In stable Rust, you can do:

fn main() {
    let mut i = 10;
    let end = 0;
    let step = -2;
    
    while i >= end {
        println!("i: {}", i);
        i += step;
    }
}

(playpen)

In nightly Rust, there's a step_by method that you can use on RangeInclusives.:

#![feature(iterator_step_by)]
fn main() {
    for i in (0..=10).rev().step_by(2) {
        println!("i: {}", i);
    }
}

(playpen)

P.S: you probably want >= in your conditional


@FenrirWolf Just realized that :stuck_out_tongue:, edit race condition

5 Likes

you can do rev on the range before doing step_by to count downwards in the second example too.

2 Likes

I'll be sure to use a Mutex next time =P

Why don't they just have a C like for loop, it seems far more convenient than Rust for loop??

Because, as you so helpfully showed, it's much easier to get it wrong. In most cases, a for _ in loop is strictly more powerful and flexible (because it works on things other than integers), and the behaviour you want from a C-style for loop can be gotten by defining an appropriate iterator.

In the remaining edge cases of really weird for loops that cover multiple variables, or can change direction, etc., those arguably shouldn't look like innocent for loops at all, so that readers know that something weird is going on.

10 Likes

Few days ago the new step_by() has become fast. But be careful because the inclusive range is still slow.

1 Like

Usually, you don't even do anything like this. For example, if you want to work on 2 array elements on every loop iteration, you do:

for slice in vec.chunks(2) {
   // slice[0], slice[1]
}
3 Likes

You could also use a combination of rev() and map(): https://gist.github.com/rust-play/0af1c5764a2b22423f288a5f080d6c72

1 Like