简体   繁体   English

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

[英]Lifetime issue when mapping an iterator over elements of a matrix

My aim is to retrieve an iterator over all elements in a matrix alongside the row number associated with each element. 我的目标是检索矩阵中所有元素的迭代器以及与每个元素关联的行号。

The following is a simplified version of the lifetime issue i'm running into. 以下是我遇到的生命周期问题的简化版本。

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

}

Here's the error I'm getting: 这是我得到的错误:

<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))
                                 ^~~~~~~~~~~~~~~~~~

Here's the playpen link . 这是围栏链接

The issue seems to stem from an inability to infer the lifetime in the map method's closure argument, though I'm unsure why. 问题似乎源于无法在map方法的闭包参数中推断生命周期,尽管我不确定为什么。

  • Can someone explain the issue here a little more clearly? 有人可以更清楚地解释这个问题吗?
  • Is it possible to produce the desired iterator another way? 是否有可能以另一种方式生产所需的迭代器?

Even if it is not very clear, the compiler can't figure out the lifetime of your inner closure 即使它不是很清楚,编译器也无法弄清楚内部闭包的生命周期

|elem| (row, elem)

Because this closure captures row from its environment (here it's the body of your outer closure), thus should not be able to outlive it. 因为这个闭包从它的环境捕获row (这里是你的外部闭包的主体),因此不应该能够比它更长寿。

Yet, you are trying to return it wrapped into the Map<> object returned by .map(..) , and so have conflicting requirements: your inner closure is asked to outlive a scope it can't outlive ! 然而,你试图将它包装回由.map(..)返回的Map<>对象中,因此有相互冲突的要求:要求你的内部闭包超过它不能超过的范围!

A simple way to escape this issue is to make your inner closure take row as an argument as well, and to do so, we can make use of: 避免这个问题的一个简单方法是使你的内部闭包也作为参数row ,为此,我们可以使用:

  • repeat(..) which creates an iterator repeating the same item forever repeat(..)创建一个永远重复同一项的迭代器
  • .zip(..) method of iterators, which allow to advance two iterators at the same time .zip(..)迭代器的方法,它允许同时前进两个迭代器

In order to something in this way: 为了这样的方式:

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

But in this case, we can make it even more simple as |(elem, my_row)| (my_row, elem) 但在这种情况下,我们可以使它更简单为|(elem, my_row)| (my_row, elem) |(elem, my_row)| (my_row, elem) looks pretty useless: |(elem, my_row)| (my_row, elem)看起来很无用:

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

Another way to increase the lifetime of the inner closure |elem| (row, elem) 另一种增加内封闭寿命的方法|elem| (row, elem) |elem| (row, elem) would be to mark it as a moving closure by simply adding the move keyword. |elem| (row, elem)只需添加move关键字即可将其标记为移动闭包。 This will also compile: 这也将编译:

let all_elems = mat.iter().enumerate().flat_map(|(row, arr)| {
    arr.iter().map(move |elem| (row, elem))
});

The same behavior can also be observed when trying to return a (boxed) closure from a function. 当尝试从函数返回(盒装)闭包时,也可以观察到相同的行为。 The following function fails to compile because the lifetime of the closure is bound by the lifetime of the local variable row : 以下函数无法编译,因为闭包的生命周期受局部变量row的生命周期的约束:

fn foo_fail() -> Box<Fn(u32) -> (u32, u32)> {
    let row = 1;
    Box::new(|elem| (row, elem))
}

Using a moving closure instead will work fine: 使用移动闭合可以正常工作:

fn foo_success() -> Box<Fn(u32) -> (u32, u32)> {
    let row = 1;
    Box::new(move |elem| (row, elem))
}

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

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