尝试实现迭代器:由于需求冲突,无法推断出适当的生命周期

时间:2017-01-22 02:17:00

标签: iterator rust lifetime

我试图在我自己的struct上实现迭代器。我的一般方法是在第一次调用next时生成并存储迭代器,然后在每次需要值时调用此迭代器。

我的最小失败示例looks like this,其核心是:

    if !self.vals.is_some() {
        self.vals = Some(Box::new({
            self.display.chars().filter(|&i| i == self.look_for)
        }) as Box<std::iter::Iterator<Item = _>>);
    }

我的代码无法编译,产生以下消息:

help: consider using an explicit lifetime parameter as shown: fn next(self: &'a mut Self) -> Option<<Self>::Item>

遵循建议没有帮助(只是导致更多编译错误,说我的实现与Iterator特征定义不兼容。

我很感激帮助了解出了什么问题以及如何解决问题。

1 个答案:

答案 0 :(得分:3)

问题在于您传递给filter的关闭需要借用self,但you can't store a reference to self in the struct itself

在这种情况下,我们可以通过在闭包中存储值的副本来解决它。这分两步完成:

  1. self.look_for分配给局部变量,并在闭包中使用局部变量。这样,闭包不会绑定到self
  2. move添加到闭包中。因此,闭包将按值捕获局部变量。
  3. 这是最终的代码:

    impl<'a> Iterator for StatefulCounter<'a> {
        type Item = bool;
        fn next(&mut self) -> Option<Self::Item> {
            if !self.vals.is_some() {
                let look_for = self.look_for;
                self.vals = Some(Box::new({
                    self.display.chars().filter(move |&i| i == look_for)
                }));
            }
    
            if let &Some(v) = &self.vals.as_mut().unwrap().next() {
                Some(expensive(v))
            } else {
                None
            }
        }
    }
    

    Box上的显式强制转换不是必需的,因此我将其删除了。