Why nested iterator closes won't copy values ​​from the outer scope

I am trying to use nested iterators where the internal iterator uses the value from the external iterator.

vec![0;10].iter().flat_map(|&a| { (0..10).map(|b|{ a + b }) }); 

error: a not long enough

  (0..10).map(|b|{ ^^^ 

note: the link must be valid for calling the method ...

This compiles if I move the inner closure ( move |b|{ ), but I don’t understand why this is necessary, given that a is an integer and can be copied instead of wrapped.

+7
closures rust borrow-checker
source share
1 answer

Both flat_map and map lazy. The internal map does not use a immediately, but tries to “save” it when needed later, and borrows a . But since a is local to the external closure, and you return the result of map , this borrowing becomes invalid. You will need to use an internal iterator:

 vec![0;10].iter().flat_map(|&a| { (0..10).map(|b|{ a + b }).collect::<Vec<_>>() }); 

Of course, this is ineffective, and it would be much better if the inner closure “held back” a . You would do this by noting the inner closure as move :

 vec![0;10].iter().flat_map(|&a| { (0..10).map(move |b|{ a + b }) }); 

Typically, the compiler will not allow you to do this because closing flat_map does not have a , it just refers to it. However, since the numeric types in Rust (for example, isize ) implement the Copy attribute, the compiler will copy a instead of moving it, giving the desired behavior. Note that this is also the reason that you are allowed to flat_map a (using |&a| ) in flat_map ; usually this would require ownership of a , not just a reference to it (which gives .iter() ).

+6
source share

All Articles