簡體   English   中英

在遞歸函數中鏈接本地迭代器時出現 Rust Lifetime 問題

[英]Rust Lifetime issue when chaining local iterator in recursive function

我有一個通用函數,它被遞歸調用,它可以接受可以轉換為迭代器的參數。

我想將作為參數傳遞的迭代器與從函數本地集合創建的迭代器鏈接起來。 這個想法是,在多次調用遞歸函數之后,會創建一個迭代器,該迭代器能夠迭代位於各自堆棧幀中的所有集合。

fn func_taking_iter<'a, I>(vals: I) -> ()
where
    I: IntoIterator<Item = &'a u32>,
    I::IntoIter: Clone,
{
    let vals = vals.into_iter();
    let mut new_val: [u32; 1] = [0u32; 1];
    for x in vals.clone() {
        new_val[0] = *x;
    }

    new_val[0] += 1u32;
    if new_val[0] == 10u32 {
        for x in vals {
            println!("Value {}", *x);
        }
        return;
    }

    let res = vals.into_iter().chain(new_val.into_iter());

    func_taking_iter(res);
}

fn main() {
    let first_val = [0u32; 1];
    func_taking_iter(first_val.iter());
}

不幸的是,當我嘗試編譯代碼時出現以下錯誤。

error[E0597]: `new_val` does not live long enough                                                 
  --> src\main.rs:20:38
   |
1  | fn func_taking_iter<'a, I>(vals: I) -> ()
   |                     -- lifetime `'a` defined here
...
20 |     let res = vals.into_iter().chain(new_val.into_iter());
   |               -----------------------^^^^^^^-------------
   |               |                      |
   |               |                      borrowed value does not live long enough
   |               argument requires that `new_val` is borrowed for `'a`
...
23 | }
   | - `new_val` dropped here while still borrowed

我對 Rust 沒有太多經驗,我被困在這里,但在我看來,這似乎不是不可能做到的事情......


編輯:改進了示例代碼,由於 Stargateur 的回答中的提示,因此僅克隆迭代器而不是整個集合

您必將你的新陣列壽命的壽命'a是你生活中的功能外,它的生命周期系統的限制,我不認為你可以今天解決這個問題,也許將來它會編譯。 但即使您可以解決生命周期問題,您最終也會出現“評估需求溢出”(E0275])。 編譯器需要推斷出無限數量的函數,因為這個具有無限鏈結構的函數有無限次調用。

我不建議在 rust 中執行這種代碼,鏈接這么多迭代器效率不高。 我認為您應該更改代碼以使用向量。 這將節省您的堆棧空間,因為無論如何您的函數都不是尾遞歸的,因此您可能會遇到堆棧溢出問題。

fn func_taking_iter_aux(vals: Vec<u32>) -> Vec<u32> {
    let new_val = vals.last().copied().unwrap_or(0) + 1;

    if new_val == 10u32 {
        vals
    } else {
        let mut vals = vals;
        vals.push(new_val);
        func_taking_iter_aux(vals)
    }
}

fn func_taking_iter<'a, I>(vals: I) -> Vec<u32>
where
    I: IntoIterator<Item = &'a u32>,
{
    func_taking_iter_aux(vals.into_iter().copied().collect())
}

fn main() {
    let vals = func_taking_iter(Some(&0));
    for x in vals {
        println!("Value {}", x);
    }
}

我盡量滿足你的要求。 這現在是一個尾遞歸函數。


請注意,代碼中的vals.clone()克隆所有數據,而不僅僅是迭代器,您應該執行let vals = vals.into_iter()然后您可以克隆迭代器並當然刪除I: Clone,

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM