为什么嵌套迭代器闭包不会从外部范围复制值

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

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

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 是一个整数并且可以被复制而不是被移动.

flat_mapmap都是懒惰的。内部 map 不会立即使用 a 而是试图“保存”它以备后用,因此借用了 a。但是由于 a 是外部闭包的局部变量,而你 return map 的结果,借用将变得无效。您需要使用内部迭代器:

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

当然这样效率不高,内部闭包"keep"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() 的结果)。