Vec <Vec <(K,V)>>的可变迭代器

Jes*_*son 2 iterator rust

我正在尝试为类型为vector的向量创建一个可变迭代器: Vec<Vec<(K, V)>>

迭代器代码:

pub struct IterMut<'a, K: 'a, V: 'a> {
    iter: &'a mut Vec<Vec<(K, V)>>,
    ix: usize,
    inner_ix: usize,
}

impl<'a, K, V> Iterator for IterMut<'a, K, V> {
    type Item = (&'a K, &'a mut V);

    #[inline]
    fn next(&mut self) -> Option<(&'a K, &'a mut V)> {

        while self.iter.len() < self.ix {
            while self.iter[self.ix].len() < self.inner_ix {
                self.inner_ix += 1;
                let (ref k, ref mut v) = self.iter[self.ix][self.inner_ix];
                return Some((&k, &mut v));
            }

            self.ix += 1;
        }

        return None;
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> src/main.rs:16:42
   |
16 |                 let (ref k, ref mut v) = self.iter[self.ix][self.inner_ix];
   |                                          ^^^^^^^^^^^^^^^^^^
   |
help: consider using an explicit lifetime parameter as shown: fn next(&'a mut self) -> Option<(&'a K, &'a mut V)>
  --> src/main.rs:11:5
   |
11 |     fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
   |     ^
Run Code Online (Sandbox Code Playgroud)

显然我有生命问题,但我不知道如何告诉编译器这应该有效.

这是你应该如何实现可变迭代器还是有更好的方法?

Mat*_* M. 6

在调试神秘的错误消息时,我发现尽可能地尝试隔离问题更容易.

第一步是将表达式分解为其基本组成部分,让我们从分割索引步骤开始:

fn next(&mut self) -> Option<(&'a K, &'a mut V)> {

    while self.iter.len() < self.ix {
        while self.iter[self.ix].len() < self.inner_ix {
            self.inner_ix += 1;
            let outer: &'a mut Vec<_> = self.iter;
            let inner: &'a mut Vec<_> = &mut outer[self.ix];
            let (ref k, ref mut v) = inner[self.inner_ix];
            return Some((&k, &mut v));
        }

        self.ix += 1;
    }

    return None;
}
Run Code Online (Sandbox Code Playgroud)

Index特性假设其输出的生命周期与其接收器的生命周期相关联,因此为了获得'a一生,我们需要接收器具有&'a生命周期,并且它向上传播,从而导致上述代码.

但是这里有一个问题:let outer: &'a mut Vec<_> = self.iter;不会编译,因为可变引用不是Copy.

那么,如何从可变引用获得可变引用(这必须是可能的,因为IndexMut获得可变引用)?

一个人使用再借款:let outer: &'a mut Vec<_> = &mut *self.iter;.

哦,哦:

error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
  --> <anon>:16:45
   |
16 |                 let outer: &'a mut Vec<_> = &mut *self.iter;
   |                                             ^^^^^^^^^^^^^^^
   |
Run Code Online (Sandbox Code Playgroud)

重新借用的参考无效'a,仅对(未命名)生命周期有效self!

为什么生锈?为什么?

因为否则会不安全.

&mut T 保证不会出现别名,但是您的方法可能会创建别名引用(如果您忘记推进索引):

#[inline]
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
    let (ref k, ref mut v) = self.iter[self.ix][self.inner_ix];
    return Some((&k, &mut v));
}
Run Code Online (Sandbox Code Playgroud)

即使你不这样做,也不能保证你没有一种rewind允许"退后"的方法.

TL; DR:你即将踩到地雷,你被转向Stack Overflow;)


好吧,但是你如何实现迭代器!.

当然,使用迭代器.正如Shepmaster(简要地)回答的那样,标准库中已经有了相同的东西FlatMap.诀窍是使用现有的迭代器来获取细节!

就像是:

use std::slice::IterMut;

pub struct MyIterMut<'a, K: 'a, V: 'a> {
    outer: IterMut<'a, Vec<(K, V)>>,
    inner: IterMut<'a, (K, V)>,
}
Run Code Online (Sandbox Code Playgroud)

然后inner只要它提供项目就消耗掉,而当它为空时你从中重新填充outer.

impl<'a, K, V> MyIterMut<'a, K, V> {
    fn new(v: &'a mut Vec<Vec<(K, V)>>) -> MyIterMut<'a, K, V> {
        let mut outer = v.iter_mut();
        let inner = outer.next()
                         .map(|v| v.iter_mut())
                         .unwrap_or_else(|| (&mut []).iter_mut());
        MyIterMut { outer: outer, inner: inner }
    }
}

impl<'a, K, V> Iterator for MyIterMut<'a, K, V> {
    type Item = (&'a K, &'a mut V);

    #[inline]
    fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
        loop {
            match self.inner.next() {
                Some(r) => return Some((&r.0, &mut r.1)),
                None => (),
            }

            match self.outer.next() {
                Some(v) => self.inner = v.iter_mut(),
                None => return None,
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

快速测试案例:

fn main() {
    let mut v = vec![
        vec![(1, "1"), (2, "2")],
        vec![],
        vec![(3, "3")]
    ];
    let iter = MyIterMut::new(&mut v);
    let c: Vec<_> = iter.collect();
    println!("{:?}", c);
}
Run Code Online (Sandbox Code Playgroud)

打印:

[(1, "1"), (2, "2"), (3, "3")]
Run Code Online (Sandbox Code Playgroud)

如预期,所以它不是完全打破,但我希望我没有依靠的&[]'static技巧(即,std::slice::IterMut执行Default).