rustinteger-overflowunsigned-integer

How to loop over 0 .. v.len() - 1 when v might be empty?


What's the correct way to loop over 0 .. v.len() - 1 when the vector v might be empty?

Consider the following code, which prints all choices of 2 elements in a vector [5, 6, 7]:

fn main() {
  let v: Vec<i32> = vec![5, 6, 7];
  for i in 0 .. v.len() - 1 {
    for j in i + 1 .. v.len() {
      println!("{} {}", v[i], v[j]);
    }
  }
}

It prints

5 6
5 7
6 7

as expected.

Now, if we instead have

let v: Vec<i32> = vec![];

then the program panics due to overflow, which is also expected.

Q: How to fix it without changing the structure and the logic of the program, and without involving signed integers?

The following are some examples of the workarounds that I don't want:

Overall, I hope that there is a clean way to handle 0 .. v.len() - 1 without any hacks.


Solution

  • Notice that, if i == v.len()-1, nothing happens in the body of the outer loop, because i+1..v.len() is an empty iterator. Therefore, the simplest way to avoid integer underflows is simply to remove the -1:

    fn main() {
      let v: Vec<i32> = vec![5, 6, 7];
      for i in 0 .. v.len() {
        for j in i + 1 .. v.len() {
          println!("{} {}", v[i], v[j]);
        }
      }
    }
    

    produces

    5 6
    5 7
    6 7
    

    and if I replace v with Vec::new(), you get no output, as expected.