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

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

问题描述

我无法表达 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.

这是修剪后的 Iterator trait:

This is the trimmed down Iterator trait:

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

请注意,&mut selfOption 之间没有生命周期连接.这意味着 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>>

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

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 块上声明的.这样做是可以的(实际上是必需的),因为您需要在结构上指定生命周期参数.然后您可以在 Itemnext() 返回类型中使用相同的 '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天全站免登陆