繁体   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