rust - 基于 lambda 的迭代器的生命周期

标签 rust

我的问题似乎与 Rust error "cannot infer an appropriate lifetime for borrow expression" when attempting to mutate state inside a closure returning an Iterator 密切相关,但我认为这并不相同。所以,这个

use std::iter;                                                                  

fn example(text: String) -> impl Iterator<Item = Option<String>> {            
    let mut i = 0;   
    let mut chunk = None;   
    iter::from_fn(move || {   
        if i <= text.len() {   
            let p_chunk = chunk;
            chunk = Some(&text[..i]);   
            i += 1;   
            Some(p_chunk.map(|s| String::from(s))) 
        } else {   
            None   
        }   
    })   
}   

fn main() {}

无法编译。编译器表示无法确定 &text[..i] 的适当生命周期。这是我能想到的最小的例子。这个想法是,有一个内部状态,它是一段文本,迭代器返回从该内部状态分配的新字符串。我是 Rust 新手,所以也许这都是显而易见的,但是我如何注释生命周期以便编译?

请注意,此示例与链接的示例不同,因为这里的 point 是作为引用传递的,而这里的 text 是移动的。另外,答案已经有一年半了,所以也许有一个更简单的方法。

编辑: 添加了 p_chunk 以强调 chunk 需要在对 next 的调用中保持不变,因此不能对于闭包来说是本地的,但应该被它捕获。

最佳答案

您的代码是尝试创建 self-referential struct 的示例,其中结构是由闭包隐式创建的。由于 textchunk 都移至闭包中,因此您可以将两者视为结构体的成员。由于 chunk 引用 text 中的内容,因此结果是一个自引用结构,当前的借用检查器不支持该结构。

虽然自引用结构通常由于移动而不安全,但在这种情况下它是安全的,因为 text 是堆分配的并且随后不会发生变化,也不会逃脱闭包。因此,text 的内容不可能移动,并且足够智能的借用检查器可以证明您尝试做的事情是安全的并允许闭包编译。

The answer to the [linked question] says that referencing through an Option is possible but the structure cannot be moved afterwards. In my case, the self-reference is created after text and chunk were moved in place, and they are never moved again, so in principle it should work.

同意 - 原则上它应该可以工作,但众所周知,当前的借用检查器不支持它。该支持需要多个新功能:借用检查器应该使用特殊情况的堆分配类型,例如 Box 或 String ,它们的移动不会影响对其内容的引用,并且这种情况也证明您没有调整大小或 mem::replace() 封闭的 String

在这种情况下,最好的解决方法是“显而易见”的方法:不要保留 chunk 切片,而是保留一对 usize 索引(或 Range )并在需要时创建切片。

关于rust - 基于 lambda 的迭代器的生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67956773/

相关文章:

json - 我如何从内容类型为 application/hal+json 的 Rocket 处理程序响应?

rust - 为什么我不能调用具有临时值的方法?

rust - 使用 required_unless 和冲突_with 与 structopt 发生 proc-macro panic

rust - 为什么在 String 上调用 .to_string() 可以避免移动错误?不是空投吗?

rust - Rust 赋值前的引用

rust - 我应该从 getter 返回 &Option<Foo> 还是 Option<&Foo> ?

rust - 为什么在闭包内克隆数据不能防止错误 "closure may outlive the current function"?

rust - 为什么循环中的不可变借用会超出其词法范围?

optimization - Rust 会优化计算范围内的循环吗?

rust - 我如何在Tokio运行时的上下文中从异步方法调用的非异步方法中等待 future ?