如何编写一个返回对自身引用的迭代器? [英] How do I write an iterator that returns references to itself?

查看:140
本文介绍了如何编写一个返回对自身引用的迭代器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法表达 Iterator 实现的返回值的生命周期。如何在不更改迭代器的返回值的情况下编译此代码?我希望它返回引用的向量。

I am having trouble expressing the lifetime of the return value of an Iterator implementation. How can I compile this code without changing the return value of the iterator? I'd like it to return a vector of references.

很明显,我没有正确使用生命周期参数,但在尝试了各种方法之后我就放弃了,我不知道该怎么做。

It is obvious that I am not using the lifetime parameter correctly but after trying various ways I just gave up, I have no idea what to do with it.

use std::iter::Iterator;

struct PermutationIterator<T> {
    vs: Vec<Vec<T>>,
    is: Vec<usize>,
}

impl<T> PermutationIterator<T> {
    fn new() -> PermutationIterator<T> {
        PermutationIterator {
            vs: vec![],
            is: vec![],
        }
    }

    fn add(&mut self, v: Vec<T>) {
        self.vs.push(v);
        self.is.push(0);
    }
}

impl<T> Iterator for PermutationIterator<T> {
    type Item = Vec<&'a T>;
    fn next(&mut self) -> Option<Vec<&T>> {
        'outer: loop {
            for i in 0..self.vs.len() {
                if self.is[i] >= self.vs[i].len() {
                    if i == 0 {
                        return None; // we are done
                    }
                    self.is[i] = 0;
                    self.is[i - 1] += 1;
                    continue 'outer;
                }
            }

            let mut result = vec![];

            for i in 0..self.vs.len() {
                let index = self.is[i];
                result.push(self.vs[i].get(index).unwrap());
            }

            *self.is.last_mut().unwrap() += 1;

            return Some(result);
        }
    }
}

fn main() {
    let v1: Vec<_> = (1..3).collect();
    let v2: Vec<_> = (3..5).collect();
    let v3: Vec<_> = (1..6).collect();

    let mut i = PermutationIterator::new();
    i.add(v1);
    i.add(v2);
    i.add(v3);

    loop {
        match i.next() {
            Some(v) => {
                println!("{:?}", v);
            }
            None => {
                break;
            }
        }
    }
}

游乐场链接

error[E0261]: use of undeclared lifetime name `'a`
  --> src/main.rs:23:22
   |
23 |     type Item = Vec<&'a T>;
   |                      ^^ undeclared lifetime


推荐答案

据我了解,你想要迭代器将引用向量返回给自己,对吧?不幸的是,在Rust中是不可能的。

As far as I understand, you want want the iterator to return a vector of references into itself, right? Unfortunately, it is not possible in Rust.

这是精简的迭代器特征:

trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Item>;
}

请注意,之间没有终身连接 code>& mut self 和选项< Item> 。这意味着 next()方法无法将引用返回到迭代器本身。您无法表达返回引用的生命周期。这基本上是你无法找到指定正确生命周期的方法 - 它看起来像这样:

Note that there is no lifetime connection between &mut self and Option<Item>. This means that next() method can't return references into the iterator itself. You just can't express a lifetime of the returned references. This is basically the reason that you couldn't find a way to specify the correct lifetime - it would've looked like this:

fn next<'a>(&'a mut self) -> Option<Vec<&'a T>>

除了这不是有效的 next() Iterator的方法 trait。

except that this is not a valid next() method for Iterator trait.

这样的迭代器(可以将引用返回给自己的迭代器)被称为流式迭代器。您可以在此处找到更多信息,这里这里,如果你想要。

Such iterators (the ones which can return references into themselves) are called streaming iterators. You can find more here, here and here, if you want.

更新。但是,您可以返回对其他结构的引用来自你的迭代器 - 这就是大多数集合迭代器的工作方式。它看起来像这样:

Update. However, you can return a reference to some other structure from your iterator - that's how most of collection iterators work. It could look like this:

pub struct PermutationIterator<'a, T> {
    vs: &'a [Vec<T>],
    is: Vec<usize>
}

impl<'a, T> Iterator for PermutationIterator<'a, T> {
    type Item = Vec<&'a T>;

    fn next(&mut self) -> Option<Vec<&'a T>> {
        ...
    }
}

注意生命周期'a 现在在 impl 块中声明。可以这样做(事实上是必需的)因为你需要在结构上指定生命周期参数。然后你可以在 Item next()中使用相同的'a 返回类型。同样,这就是大多数集合迭代器的工作方式。

Note how lifetime 'a is now declared on impl block. It is OK to do so (required, in fact) because you need to specify the lifetime parameter on the structure. Then you can use the same 'a both in Item and in next() return type. Again, that's how most of collection iterators work.

这篇关于如何编写一个返回对自身引用的迭代器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆