首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何延长Rust中迭代器适配器内临时变量的生存期?

如何延长Rust中迭代器适配器内临时变量的生存期?
EN

Stack Overflow用户
提问于 2019-06-20 17:34:51
回答 1查看 825关注 0票数 1

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

代码语言:javascript
复制
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())
    }
}

试图编译此示例将产生一个生存期错误:

代码语言:javascript
复制
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为止,但是我不知道怎么做。

请注意,结构实现不能更改。锈蚀版本为1.34.2,2018年版

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-21 15:29:34

延长此对象的生存期。

你不能这么做,就这样。事情不是这样运作的。

另请参阅:

这里有一个简单的复制:

代码语言:javascript
复制
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

代码语言:javascript
复制
fn example(outer: impl Iterator<Item = Inner>) {
    outer.flat_map(|i| i.iter().map(|v| v.clone()).collect::<Vec<_>>());
}

我所知道的避免这种情况的唯一可能性是使用像租房参考这样的机箱。

另请参阅:

如果您有可能更改Inner,则应该使用迭代器变体。然后,由于迭代器获得了所有权,因此该值不需要存在于闭包之外。

代码语言:javascript
复制
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()
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56691225

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档