为什么嵌套的迭代器闭包不会从外部作用域复制值

时间:2016-07-24 10:58:17

标签: closures rust borrow-checker

我试图使用嵌套迭代器,其中内部迭代器使用外部迭代器中的值。

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

错误:a活得不够长

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

注意:引用必须对方法调用有效...

如果我移动内部闭包(move |b|{),这会编译,但我不明白为什么它是必要的,因为a是一个整数并且可以被复制而不是被移动

1 个答案:

答案 0 :(得分:7)

flat_mapmap都是懒惰的。内部map不会立即使用a,但会尝试“保存”它以便以后需要它时借用a。但由于a是外部闭包的本地,并且您返回map的结果,因此借用将变为无效。您需要使用内部迭代器:

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

当然,这样做效率不高,内部封闭会更好“保持&#34; a。您可以通过将内部闭包标记为move

来完成此操作
vec![0;10].iter().flat_map(|&a| {
    (0..10).map(move |b|{
        a + b
    })
});

通常情况下,编译器不允许你这样做,因为flat_map闭包不拥有a,它只是对它的引用。然而, 由于Rust中的数字类型(如isize)实现了Copy特征,编译器将复制a而不是尝试移动它,从而提供您想要的行为。请注意,这也是允许您在a中取消引用|&a|(使用flat_map)的原因;通常需要拥有a,而不仅仅是对它的引用(这是.iter()产生的)。