Ошибка Rust [E0373]: замыкание может пережить текущую функцию, но оно заимствует `iteration_index` - PullRequest
0 голосов
/ 08 февраля 2019

У меня есть два вектора itertools::MinMaxResult.Мне нужно перебрать первый вектор, и для каждого элемента, перебрать второй вектор, проверяя, равен ли минимум первого вектора максимуму любых элементов второго вектора, и наоборот.Вот MCVE того, что я попробовал:

use itertools::MinMaxResult; // itertools = "0.8.0"
use itertools::MinMaxResult::*;

pub fn mcve() -> Vec<(usize, usize)> {

    // dummy variables to make the MCVE compile
    let num_rows = 0;
    let num_cols = 0;
    let row_minmax: Vec<MinMaxResult<&u64>> = vec![];
    let col_minmax: Vec<MinMaxResult<&u64>> = vec![];

    // Problematic code:
    (0..num_rows)
            .flat_map(|row_index| {
                (0_usize..num_cols).filter_map(|col_index| {
                    match (row_minmax[row_index], col_minmax[col_index]) {
                        (MinMax(a, _b), MinMax(_c, d)) if a == d =>
                            Some((row_index, col_index)),
                        (MinMax(_a, b), MinMax(c, _d)) if b == c =>
                            Some((row_index, col_index)),
                        _ => None,
                    }
                })
            })
            .collect::<Vec<(usize, usize)>>()
}

Ссылка на игровую площадку с полным кодом

Я получаю следующую ошибку:

error[E0373]: closure may outlive the current function, but it borrows `row_index`,
which is owned by the current function
  --> src/main.rs:15:48
   |
15 |                 (0_usize..num_cols).filter_map(|col_index| {
   |                                                ^^^^^^^^^^^ may outlive 
                                                    borrowed value `row_index`
16 |                     match (row_minmax[row_index], col_minmax[col_index]) {
   |                                       --------- `row_index` is borrowed here
   |
note: closure is returned here
  --> src/main.rs:15:17
   |
15 | /                 (0_usize..num_cols).filter_map(|col_index| {
16 | |                     match (row_minmax[row_index], col_minmax[col_index]) {
17 | |                         (MinMax(a, _b), MinMax(_c, d)) if a == d => 
                                   Some((row_index, col_index)),
18 | |                         (MinMax(_a, b), MinMax(c, _d)) if b == c => 
                                   Some((row_index, col_index)),
19 | |                         _ => None,
20 | |                     }
21 | |                 })
   | |__________________^
help: to force the closure to take ownership of `row_index` 
(and any other referenced variables), use the `move` keyword
   |
15 |                 (0_usize..num_cols).filter_map(move |col_index| {
   |                                                ^^^^^^^^^^^^^^^^

Если я добавлю move, как предлагает компилятор, я получу в два раза больше ошибок , так что это не поможет.Как мне избавиться от этой ошибки?

1 Ответ

0 голосов
/ 08 февраля 2019

Ваш связанный гист имеет целую кучу типичных ошибок "борьба с заемщиком".Вот как их решить:

  • используйте move в качестве предложения компилятора, но убедитесь, что все перемещенные значения реализуют Copy.
  • Индексы итерации типа usizeуже реализован Copy, поэтому здесь делать нечего.
  • Векторы проблематичны, поэтому просто возьмите их неизменные ссылки и вместо этого передайте неизменные ссылки в замыкания.
  • Вашinto_par_iter вызывает не связанную проблему владения.Просто используйте par_iter вместо этого, тогда вы будете перебирать ссылки, а не фактические значения, и вы не уничтожите свою матрицу, пока вы перебираете ее.

Здесь компилируется:

use itertools::MinMaxResult; // itertools = "0.8.0"
use itertools::MinMaxResult::*;
use itertools::Itertools;
use rayon::prelude::*; // rayon = "1.0.3"

pub fn find_saddle_points(input: &[Vec<u64>]) -> Vec<(usize, usize)> {
    let flattened_matrix: Vec<(&u64)> = input.into_par_iter().flatten().collect();
    if flattened_matrix.is_empty() {
        vec![]
    } else {
        let num_rows = input.len();
        let num_cols = input[0].len();

        let row_minmax: Vec<MinMaxResult<&u64>> = input
            .iter()
            .map(|row| row.iter().minmax())
            .collect::<Vec<MinMaxResult<&u64>>>();

        let input_tranpose: Vec<Vec<u64>> = (0_usize..num_cols)
            .into_par_iter()
            .map(|col_index| {
                (0_usize..num_rows)
                    .map(|row_index| input[row_index][col_index])
                    .collect::<Vec<u64>>()
            })
            .collect();

        // don't take ownership! 
        // Use `par_iter` instead, then `col` will be a reference,
        // and the borrow-checker is happy.
        let col_minmax: Vec<MinMaxResult<&u64>> = input_tranpose
            .par_iter()   
            .map(|col| col.iter().minmax())
            .collect();

        let rmm_ref = &row_minmax;
        let cmm_ref = &col_minmax;
        (0_usize..num_rows)
            .flat_map(|row_index| {
                (0_usize..num_cols).filter_map(move |col_index| {
                    match (rmm_ref[row_index], cmm_ref[col_index]) {
                        (MinMax(a, _b), MinMax(_c, d)) if a == d => 
                            Some((row_index, col_index)),
                        (MinMax(_a, b), MinMax(c, _d)) if b == c => 
                            Some((row_index, col_index)),
                        _ => None,
                    }
                })
            })
            .collect::<Vec<(usize, usize)>>()
    }
}

fn main(){}
...