Why nested iterator closures won't copy values from outer scope

你。 提交于 2019-12-01 01:17:01

问题


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:


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).



来源:https://stackoverflow.com/questions/38551294/why-nested-iterator-closures-wont-copy-values-from-outer-scope

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!