简体   繁体   English

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

[英]How to copy instead of borrow an i64 into a closure in Rust?

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)
        )
    });
}

Now, when I compile that with rustc I get the following error message:现在,当我用rustc编译它时,我收到以下错误消息:

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

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?但在我的理解中, idi64类型,因此应该能够被复制到捕获中,这正是我需要的?

I've also tried to inline the id variable but to no avail:我也试过内联id变量,但无济于事:

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?那么如何将我的整数复制到闭包中而不是借用它呢?

I tried using move , but rustc doesn't like that either:我尝试使用move ,但rustc也不喜欢这样:

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

So I'd somehow need to get rustc to only move/copy some but not the other variable?所以我不知何故需要让rustc只移动/复制一些而不是其他变量?

When you create a closure in Rust, it captures the variables either by value or by reference.当您在 Rust 中创建闭包时,它会通过值或引用来捕获变量。 A mix of both is impossible.两者的混合是不可能的。 By default, it captures by reference, but with the move keyword, it captures by value ( ie it moves the captured variables inside the closure).默认情况下,它按引用捕获,但使用move关键字,它按值捕获(它在闭包内移动捕获的变量)。

So, in your first code, you need to move id inside the closure:因此,在您的第一个代码中,您需要将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))
    });
}

Then you ask if you can "inline" ids :然后你问你是否可以“内联” 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]))
    });
}

You cannot put ids at all in your inner closure, because you are already inside a FnMut closure (that requires exclusive access).您根本不能将ids放在内部闭包中,因为您已经在FnMut闭包中(需要独占访问)。 Thus, you cannot borrow or move ids because it is already borrowed by the FnMut closure.因此,您不能借用或移动ids因为它已经被FnMut闭包借用了。 Minimal reproduction:最小复制:

fn main() {
    let mut i = 0;

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

    closure()();
}

You can move the variable into closure with move keyword.您可以使用move关键字将变量移动到闭包中。 Here you need to change the closure like:在这里,您需要更改闭包,例如:

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

Playground 操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM