簡體   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