如何在Rust中延长迭代器适配器内部临时变量的寿命?

西布兰

我有一个方法make_iter()可以在Rust中创建带有多个适配器的Iterator,可以将其简化为以下MCVE:

fn make_iter(first: &First) -> Box<dyn Iterator<Item = String> + '_> {
    Box::new(first.make_objects().flat_map(|second| {
        second
            .iter()
            .filter(|third| third.as_str() != "t2")
            .flat_map(|third| vec![format!("{}.A", third), format!("{}.B", third)].into_iter())
            .chain(
                vec![
                    format!("{}.A", second.name()),
                    format!("{}.B", second.name()),
                ]
                .into_iter(),
            )
    }))
}

pub fn main() {
    let first = First {};
    for i in make_iter(&first) {
        println!("{}", i);
    }
}

struct First {}

impl First {
    fn make_objects(&self) -> Box<dyn Iterator<Item = Second> + '_> {
        Box::new(
            vec![
                Second::new("s1".to_string()),
                Second::new("s2".to_string()),
                Second::new("s3".to_string()),
            ]
            .into_iter(),
        )
    }
}

struct Second {
    name: String,
    objects: Vec<String>,
}

impl Second {
    fn new(name: String) -> Second {
        Second {
            name,
            objects: vec!["t1".to_string(), "t2".to_string(), "t3".to_string()],
        }
    }

    fn name(&self) -> &str {
        &self.name
    }

    fn iter(&self) -> Box<dyn Iterator<Item = &String> + '_> {
        Box::new(self.objects.iter())
    }
}

尝试编译此示例会产生生命周期错误:

error[E0597]: `second` does not live long enough
  --> src/main.rs:3:9
   |
3  |         second
   |         ^^^^^^ borrowed value does not live long enough
...
14 |     }))
   |     - `second` dropped here while still borrowed

这是可以理解的,因为second对象是一个临时对象,并且从同一个闭包返回的迭代器尝试借用它,但失败的原因second是在闭包的结尾处删除了该对象。我的目标是延长该对象的寿命,直到删除引用它的Iterator,但我不知道如何做。

注意,结构实现不能更改。Rust版本是1.34.2,2018版

Shepmaster

延长此对象的寿命

期间,您无法执行此操作。根本不是事情如何运作。

也可以看看:

这是一个简单的复制:

use std::iter;

fn example(outer: impl Iterator<Item = Inner>) {
    outer.flat_map(|i| i.iter().map(|v| v.clone()));
}

struct Inner;

impl Inner {
    fn iter(&self) -> impl Iterator<Item = &()> + '_ {
        iter::empty()
    }
}

由于存在无法更改的限制Inner,因此最简单的解决方案是更加积极主动collect

fn example(outer: impl Iterator<Item = Inner>) {
    outer.flat_map(|i| i.iter().map(|v| v.clone()).collect::<Vec<_>>());
}

我知道避免发生这种情况的唯一可能性是使用一个板条箱,例如rentalowning_ref

也可以看看:

如果您有可能进行更改Inner,则应制作一个消耗量大的迭代器变体。然后,该值不需要超出闭包,因为迭代器已拥有所有权。

use std::iter;

fn example(outer: impl Iterator<Item = Inner>) {
    outer.flat_map(|i| i.into_iter().map(|v| v));
}

struct Inner;

impl Inner {
    fn into_iter(self) -> impl Iterator<Item = ()> {
        iter::empty()
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在回收器适配器中添加片段?

迭代器与适配器设计模式

如何在 OnSuccessListener 中的 recyclerview 适配器中传递侦听器

单击活动类中的按钮,如何在适配器的微调器上过滤列表

如何在Firebase回收器适配器中实现recyclerview ItemClickListener()?

Android 编程:如何在微调器的 onItemSelected 适配器中永久更改语言

如何在 ChartJS 中包含适配器和插件

如何在片段中调用RecyclerView适配器的方法

addAll如何在Android List适配器中工作?

如何在适配器中启动活动

如何在 recyclerview 适配器中与 Viewmodel 交互?

如何在Linux Mint中更改适配器名称

如何在适配器中启动Activity?

如何在Hubot脚本中获取适配器名称?

如何在recyclerView的适配器中调用scrollToPosition(position)?

如何在Android中自定义适配器?

如何在分段适配器(Android)中获得位置?

如何在Android的适配器中设置数据

如何在活动中更新适配器的文本视图

如何在RecyclerView适配器的onBindViewHolder中声明overridePendingTransition?

如何在其适配器的onBindViewHolder中更新recyclerView?

如何在其适配器中刷新android listview

如何在片段中声明适配器?

如何在MobileFirst 7.0中调试SOAP适配器

如何在Android适配器中传递Json数据

如何在自定义适配器内部的生成的按钮中设置一些操作

如何在recycleview适配器中设置布局可见性,我的适配器代码是

输出迭代器适配器以计数但不复制

Rust字符串生存期和迭代器适配器(生存期编译错误)