2016-07-24 26 views
7

我试图使用嵌套迭代器,其中内部迭代器使用来自外部迭代器的值。为什么嵌套的迭代器闭包不会复制外部范围的值

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

此编译如果我将内罩(move |b|{),但我不明白为什么它是必要的,因为a是一个整数,可以被复制而不是移动。

+0

https://doc.rust-lang.org/book/closures.html#closures-and-their-environment 默认情况下,短暂关闭借用其环境。随着'移动'它取得了环境的所有权。如果价值可复制,它不能被移动并将被复制。 – aSpex

回答

6

flat_mapmap都是懒惰的。内部的map不立即使用a,而是尝试“保存”它以后需要的时间,因此借用a。但由于a位于外部封闭位置,因此您返回map的结果,则该借款将变为无效。你会需要消耗内部迭代器:

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

当然,这不是有效的,并且这将是多的内罩“养” a更好。你会通过标记内罩为move做到这一点:

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

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