Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Re-using a range for iteration

Tags:

rust

Im trying to understand how to use ranges with iterators. If I declare a range and use it with an iterator, is it possible to re-use that range with another iterator? For example this does not compile:

fn main() {
    let smallr = 0..10;
    for i in smallr {
        println!("value is {}", i);
    }

    //let smallr = 0..15;  re-defining smallr will work!
    let sum  = smallr.fold(0, |sum, x| sum + x);
    println!("{}", sum);
}
like image 373
kezzos Avatar asked Sep 27 '22 12:09

kezzos


1 Answers

The range type Range does not implement Copy. Therefor using a range in a for loop will consume it. If you want to create a copy of a range, you can use .clone():

for i in smallr.clone() {
    println!("value is {}", i);
}

Note that this might cause confusing behavior when used on a mutable range (which afaik is the reason why Range does not implement Copy). A range is also an iterator at the same time. If you only partially consume the iterator and then clone it, You get a clone of the partially consumed iterator.

As an example of the pitfall:

fn main() {
    let mut smallr = 0..10;

    println!("first: {:?}", smallr.next());
    for i in smallr.clone() {
        println!("value is {}", i);
    }
}

prints

first: Some(0)
value is 1
value is 2
value is 3
value is 4
value is 5
value is 6
value is 7
value is 8
value is 9

which shows that the first value of the range is not part of the cloned iterator.

like image 96
oli_obk Avatar answered Oct 06 '22 01:10

oli_obk