8
votes

I'm trying to use nested iterators, where the inner iterator uses value from the outer iterator.

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

error: a does not live long enough

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

note: reference must be valid for the method call...

This compiles if I move the inner closure (move |b|{), but I don't understand why it is necessary, given that a is an integer and could have been copied instead of moved.

1
doc.rust-lang.org/book/… In short closures borrows its environment by default. With move it take ownership of the environment. If value copyable it can not be moved and will be copied.aSpex

1 Answers

7
votes

Both flat_map and map are lazy. The inner map does not use a immediately but tries to “save” it for when it will be needed later thus borrows a. But since a is local to the outer closure and you return map's result, that borrow would become invalid. You would need to consume the inner iterator:

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

Of course that's not efficient, and it would be much better for the inner closure to "keep" a. You would do this by marking the inner closure as move:

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

Normally, the compiler would not let you do this, because the flat_map closure does not own a, it merely has a reference to it. However, since the numeric types in Rust (like isize) implement the Copy trait, the compiler will copy a instead of trying to move it, giving the behavior you want. Note that this is also the reason why you are allowed to dereference a (using |&a|) in the flat_map; normally that would have required owning a, not merely a reference to it (which is what .iter() yields).