代码之家  ›  专栏  ›  技术社区  ›  Abhijit Sarkar

如何修复“闭包可能比当前函数更有效”

  •  0
  • Abhijit Sarkar  · 技术社区  · 2 年前

    我有以下代码:

    pub fn find_saddle_points(input: &[Vec<u64>]) -> Vec<(usize, usize)> {
      let mut row_max: Vec<HashSet<usize>> = vec![HashSet::new(); input.len()];
      let mut col_min: Vec<HashSet<usize>> = vec![HashSet::new(); input[0].len()];
      ...
      row_max.iter().enumerate()
        .flat_map(|(row, cols)| {
            cols.iter()
                .filter(|c| col_min[**c].contains(&row))
                .map(|c| (row, *c))
        })
        .collect()
    }
    

    编译失败。

    error[E0373]: closure may outlive the current function, but it borrows `row`, which is owned by the current function
      --> src/lib.rs:48:21
       |
    48 |             .filter(|c| col_min[**c].contains(&row))
       |                     ^^^                        --- `row` is borrowed here
       |                     |
       |                     may outlive borrowed value `row`
       |
    note: closure is returned here
      --> src/lib.rs:47:9
       |
    47 | /         cols.iter()
    48 | |             .filter(|c| col_min[**c].contains(&row))
    49 | |             .map(|c| (row, *c))
       | |_______________________________^
    help: to force the closure to take ownership of `row` (and any other referenced variables), use the `move` keyword
       |
    48 |             .filter(move |c| col_min[**c].contains(&row))
       |                     ++++
    
    error[E0373]: closure may outlive the current function, but it borrows `row`, which is owned by the current function
      --> src/lib.rs:49:18
       |
    49 |             .map(|c| (row, *c))
       |                  ^^^  --- `row` is borrowed here
       |                  |
       |                  may outlive borrowed value `row`
       |
    note: closure is returned here
      --> src/lib.rs:47:9
       |
    47 | /         cols.iter()
    48 | |             .filter(|c| col_min[**c].contains(&row))
    49 | |             .map(|c| (row, *c))
       | |_______________________________^
    help: to force the closure to take ownership of `row` (and any other referenced variables), use the `move` keyword
       |
    49 |             .map(move |c| (row, *c))
       |                  ++++
    

    我可以使用 move map 因为没有人使用 row 之后,但我不能使用 移动 filter 自从 col_min 具有类型 Vec<HashSet<usize>> ,它不实现 Copy 特质如何修复此问题?

    1 回复  |  直到 2 年前
        1
  •  2
  •   cdhowie    2 年前

    通过引用在 move 闭包,在闭包外部创建引用,然后在闭包中使用该引用;引用将移动到闭包中,而不是它引用的值。

      row_max.iter().enumerate()
        .flat_map(|(row, cols)| {
            // Shadow col_min with a reference to the outer variable.  The closure
            // will capture this reference instead of the col_min value above.
            let col_min = &col_min;
            cols.iter()
                .filter(move |c| col_min[**c].contains(&row))
                .map(move |c| (row, *c))
        })
        .collect()
    

    ( Playground )