如何在 Rust 中复制而不是借用 i64 到闭包中? [英] How to copy instead of borrow an i64 into a closure in Rust?

查看:14
本文介绍了如何在 Rust 中复制而不是借用 i64 到闭包中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的代码有以下最小示例:

I have the following minimal example of my code:

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(|n| 
            (n.clone(), id)
        )
    });
}

现在,当我用 rustc 编译它时,我收到以下错误消息:

Now, when I compile that with rustc I get the following error message:

error[E0597]: `id` does not live long enough
  --> main.rs:12:16
   |
11 |         v.iter().map(|n| 
   |                      --- capture occurs here
12 |             (n.clone(), id)
   |                         ^^ borrowed value does not live long enough
13 |         )
14 |     });
   |     -- borrowed value needs to live until here
   |     |
   |     borrowed value only lives until here

但据我了解,id 属于 i64 类型,因此应该能够被复制到捕获中,这正是我所需要的吗?

But in my understanding, id is of type i64 and should therefore be able to be copied into the capture, with would be exactly what I need?

我也尝试过内联 id 变量,但无济于事:

I've also tried to inline the id variable but to no avail:

error[E0597]: `i` does not live long enough
  --> main.rs:11:21
   |
10 |             v.iter().map(|n| 
   |                          --- capture occurs here
11 |                 (n.clone(), ids[i])
   |                                 ^ borrowed value does not live long enough
12 |             )
13 |         });
   |         -- borrowed value needs to live until here
   |         |
   |         borrowed value only lives until here

那么我怎样才能将我的整数复制到闭包中而不是借用它呢?

So how can I copy my integer into the closure instead of borrowing it?

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

I tried using move, but rustc doesn't like that either:

error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
  --> main.rs:10:17
   |
7  |         let ids : Vec<i64> = vec![10, 20];
   |             --- captured outer variable
...
10 |             v.iter().map(move |n| 
   |                          ^^^^^^^^ cannot move out of captured outer variable in an `FnMut` closure

所以我需要让 rustc 只移动/复制一些变量而不是其他变量?

So I'd somehow need to get rustc to only move/copy some but not the other variable?

推荐答案

当你在 Rust 中创建闭包时,它会通过值或引用来捕获变量.两者的混合是不可能的.默认情况下,它通过引用捕获,但使用 move 关键字,它按值捕获(它将捕获的变量移动到闭包内).

When you create a closure in Rust, it captures the variables either by value or by reference. A mix of both is impossible. By default, it captures by reference, but with the move keyword, it captures by value (i.e. it moves the captured variables inside the closure).

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

So, in your first code, you need to move id inside the closure:

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:

Then you ask if you can "inline" ids:

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)| {
        v.iter().map(|n| (n.clone(), ids[i]))
    });
}

您根本不能将 ids 放在内部闭包中,因为您已经在 FnMut 闭包中(需要独占访问).因此,您不能借用或移动 ids,因为它已经被 FnMut 闭包借用了.最小复制:

You cannot put ids at all in your inner closure, because you are already inside a FnMut closure (that requires exclusive access). Thus, you cannot borrow or move ids because it is already borrowed by the FnMut closure. Minimal reproduction:

fn main() {
    let mut i = 0;

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

    closure()();
}

这篇关于如何在 Rust 中复制而不是借用 i64 到闭包中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆