繁体   English   中英

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

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

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

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

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

}

这是我得到的错误:

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

这是围栏链接

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

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

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

|elem| (row, elem)

因为这个闭包从它的环境捕获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))
});

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

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

另一种增加内封闭寿命的方法|elem| (row, elem) |elem| (row, elem)只需添加move关键字即可将其标记为移动闭包。 这也将编译:

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

当尝试从函数返回(盒装)闭包时,也可以观察到相同的行为。 以下函数无法编译,因为闭包的生命周期受局部变量row的生命周期的约束:

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

使用移动闭合可以正常工作:

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