如何将i64复制而不是借用到Rust中的闭包中?

如何将i64复制而不是借用到Rust中的闭包中?,rust,copy,borrowing,Rust,Copy,Borrowing,我的代码有以下最简单的示例: fn main() { 让名字:Vec=Vec[ vec![“Foo1.to_string(),“Foo2.to_string()], vec![“Bar1.to_string(),“Bar2.to_string()] ]; 让id:Vec=Vec![10,20]; name.iter().enumerate().flat|u映射(|(i,v)|{ 设id:i64=id[i]; v、 iter().map(| n | (n.clone(),id) ) }); }

我的代码有以下最简单的示例:

fn main()
{
让名字:Vec=Vec[
vec![“Foo1.to_string(),“Foo2.to_string()],
vec![“Bar1.to_string(),“Bar2.to_string()]
];
让id:Vec=Vec![10,20];
name.iter().enumerate().flat|u映射(|(i,v)|{
设id:i64=id[i];
v、 iter().map(| n |
(n.clone(),id)
)
});
}
现在,当我用
rustc
编译它时,我得到以下错误消息:

错误[E0597]:`id`寿命不够长
-->main.rs:12:16
|
11 | v.iter().map(| n |
|---捕获发生在这里
12 |(n.clone(),id)
|^^借来的价值无法维持足够长的时间
13 |         )
14 |     });
|--借来的价值需要一直存在到现在
|     |
|借来的价值只在这里存在
但据我理解,
id
属于
i64
类型,因此应该能够复制到捕获中,这正是我需要的吗

我还尝试内联
id
变量,但没有成功:

错误[E0597]:`i`活得不够长
-->main.rs:11:21
|
10 | v.iter().map(| n |
|---捕获发生在这里
11 |(n.clone(),id[i])
|^借来的价值不够长久
12 |             )
13 |         });
|--借来的价值需要一直存在到现在
|         |
|借来的价值只在这里存在
那么,如何将整数复制到闭包中,而不是借用它呢

我尝试使用
move
,但
rustc
也不喜欢这样:

error[E0507]:无法移出'FnMut'闭包中捕获的外部变量
-->main.rs:10:17
|
7 |让id:Vec=Vec![10, 20];
|---捕获的外部变量
...
10 | v.iter().map(move | n |
|^^^^^^^^^无法移出'FnMut'闭包中捕获的外部变量

因此,我需要让
rustc
只移动/复制一些变量,而不复制另一个变量?

您可以使用
move
关键字将变量移动到闭包中。这里您需要更改闭包,如下所示:

v.iter().map(move |n|  // move is the keyword for moving variables into closure scope.
    (n.clone(), id)
)

在Rust中创建闭包时,它通过值或引用捕获变量。两者不可能混合使用。默认情况下,它通过引用捕获变量,但使用
move
关键字,它通过值捕获变量(即,它在闭包中移动捕获的变量)

因此,在第一个代码中,您需要在闭包内移动
id

fn main() {
    let names: Vec<Vec<String>> = vec![
        vec!["Foo1".to_string(), "Foo2".to_string()],
        vec!["Bar1".to_string(), "Bar2".to_string()],
    ];
    let ids: Vec<i64> = vec![10, 20];

    names.iter().enumerate().flat_map(|(i, v)| {
        let id: i64 = ids[i];
        v.iter().map(move |n| (n.clone(), id))
    });
}
您根本无法将
ids
放入内部闭包中,因为您已经在
FnMut
闭包中(需要独占访问)。因此,您无法借用或移动
ids
,因为它已经被
FnMut
闭包借用。最小复制:

fn main() {
    let mut i = 0;

    let mut closure = || {
        i = 2;
        || {
            println!("i = {}", i);
        }
    };

    closure()();
}

使用
move
。可复制的东西不是移动的,而是复制的。让我找到副本。@Boiethios也不起作用,我会将错误添加到你的两个closure中。我刚刚回答了一个快速帮助的问题,如果是,可以很高兴地投赞成票duplicate@Boiethios如果我同时向两个闭包中添加,则会出现相同的错误。第一个版本与AkinerA中的一样工作lkan的回答,但是我可以让第二个版本也这样工作吗?这是有道理的,但是编译器将错误消息指向
I
,而不是
ids
,那么这只是一个错误的错误消息吗?@msrd0这是另一个问题:您尝试返回包含
I
引用的内容,但是
I
是从内部声明的e您的可变闭包。好的,我明白了,因为
map
确实拥有闭包的所有权,所以编译器不能保证在
I
超出范围之前执行它。从编译器的错误消息中这不是很清楚。谢谢。我不认为您的最后一段是准确的。您可以借用内部cl中的
ids
osure,它是不能借用的
i
(因为它属于外部闭包)。另一方面,你可以移动
i
(因为它是
Copy
),但您不能移动
ids
,因为外部闭包只借用了它。在移动
i
时,您需要借用
ids
,这是不可能的,您可以通过两者的混合来实现-这在技术上是准确的,但正如trentcl所示,您可以获取一个显式引用,然后将引用移入,从而有效地获得混合。
fn main() {
    let mut i = 0;

    let mut closure = || {
        i = 2;
        || {
            println!("i = {}", i);
        }
    };

    closure()();
}