代码之家  ›  专栏  ›  技术社区  ›  msrd0 Gordon Linoff

如何复制而不是借一个I64到一个生锈的封闭?

  •  1
  • msrd0 Gordon Linoff  · 技术社区  · 6 年前

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

    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 我收到以下错误消息:

    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 因此应该能够被复制到捕获中,这正是我需要的吗?

    我也试着把 身份证件 变量,但无效:

    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
    

    那么,如何将整数复制到闭包中而不是借用它呢?

    我试着用 move 但是 鲁斯特 也不喜欢这样:

    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
    

    所以我需要 鲁斯特 只移动/复制一部分变量而不移动另一个变量?

    2 回复  |  直到 6 年前
        1
  •  3
  •   Shepmaster Tim Diekmann    6 年前

    当您在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 :

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

    你不能放 身份证 在你的内部封闭,因为你已经在一个 FnMut 关闭(需要独占访问)。因此,你不能借用或移动 身份证 因为它已经被 FNMUT 关闭。最小复制:

    fn main() {
        let mut i = 0;
    
        let mut closure = || {
            i = 2;
            || {
                println!("i = {}", i);
            }
        };
    
        closure()();
    }
    
        2
  •  2
  •   Shepmaster Tim Diekmann    6 年前

    您可以使用 move 关键字。在这里,您需要像以下那样更改闭包:

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

    Playground