将迭代器映射到矩阵的元素时的生命周期问题

min*_*ree 5 iterator lifetime rust

我的目标是检索矩阵中所有元素的迭代器以及与每个元素关联的行号.

以下是我遇到的生命周期问题的简化版本.

fn main() {

    let mat = [ [1i32, 2,    3],
                [4,    5,    6],
                [7,    8,    9] ];

    // Create an iterator that produces each element alongside its row number.
    let all_elems = mat.iter().enumerate().flat_map(|(row, arr)| {
        arr.iter().map(|elem| (row, elem)) // Error occurs here.
    });

    for (row, elem) in all_elems {
        println!("Row: {}, Elem: {}", row, elem);
    }

}
Run Code Online (Sandbox Code Playgroud)

这是我得到的错误:

<anon>:10:9: 10:43 error: cannot infer an appropriate lifetime for lifetime parameter 'r in function call due to conflicting requirements
<anon>:10         arr.iter().map(|elem| (row, elem))
                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<anon>:10:24: 10:42 note: first, the lifetime cannot outlive the expression at 10:23...
<anon>:10         arr.iter().map(|elem| (row, elem))
                                 ^~~~~~~~~~~~~~~~~~
<anon>:10:24: 10:42 note: ...so type `|&i32| -> (uint, &i32)` of expression is valid during the expression
<anon>:10         arr.iter().map(|elem| (row, elem))
                                 ^~~~~~~~~~~~~~~~~~
<anon>:10:9: 10:43 note: but, the lifetime must be valid for the method call at 10:8...
<anon>:10         arr.iter().map(|elem| (row, elem))
                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<anon>:10:24: 10:42 note: ...so that argument is valid for the call
<anon>:10         arr.iter().map(|elem| (row, elem))
                                 ^~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

这是围栏链接.

问题似乎源于无法推断map方法的闭包参数中的生命周期,尽管我不确定为什么.

  • 有人可以更清楚地解释这个问题吗?
  • 是否有可能以另一种方式生产所需的迭代器?

Lev*_*ans 5

即使它不是很清楚,编译器也无法弄清楚内部闭包的生命周期

|elem| (row, elem)
Run Code Online (Sandbox Code Playgroud)

因为这个闭包row从它的环境中捕获(这里它是你的外部封闭体),因此不应该比它更活跃.

然而,你试图将它包装回所返回的Map<>对象中.map(..),因此需要有相互冲突的要求:你的内部封闭被要求超过它不能超过的范围!

解决这个问题的一个简单方法是将内部闭包row作为参数,为此,我们可以使用:

  • repeat(..) 这会创建一个永远重复同一项的迭代器
  • .zip(..) 迭代器的方法,允许同时前进两个迭代器

为了这样的方式:

let mut all_elems = mat.iter().enumerate().flat_map(|(row, arr)| {
    arr.iter()
       .zip(repeat(row))
       .map(|(elem, my_row)| (my_row, elem))
});
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,我们可以使它更简单,因为|(elem, my_row)| (my_row, elem)看起来很无用:

let mut all_elems = mat.iter().enumerate().flat_map(|(row, arr)| {
    repeat(row).zip(arr.iter())
});
Run Code Online (Sandbox Code Playgroud)