在Rust中实现自定义迭代器时出现无限循环

问题描述:

我试图执行列表zipper。到目前为止,我有:在Rust中实现自定义迭代器时出现无限循环

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)] 
pub struct ListZipper { 
    pub focus: Option<Tile>, 
    pub left: VecDeque<Tile>, 
    pub right: VecDeque<Tile>, 
} 

impl PartialEq for ListZipper { 
    fn eq(&self, other: &ListZipper) -> bool { 
     self.left == other.left && self.focus == other.focus && self.right == other.right 
    } 
} 

我现在想实现一个迭代器

impl Iterator for ListZipper { 
    type Item = Tile; 

    fn next(&mut self) -> Option<Tile> { 
     self.left.iter().chain(self.focus.iter()).chain(self.right.iter()).next().map(|w| *w)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
    } 
} 

在我的脑海这是有道理的。当遍历ListZipper时,我想遍历left,然后focus,然后right。所以我链接这些迭代器,并返回next()

如果ListZipper所有字段为空,这工作得很好。只要不是空的,则通过ListZipper迭代导致无限循环。

问题不在于链条。如果我用例如self.left.iter()left不是空的,问题是一样的。同样适用于focusright

我想打印在迭代的所有元素,它似乎从前面经过VecDeque备份,然后卡住。即当它到达后面时,next()不会前进光标。

为什么?

我意识到我可能不希望ListZipper自己是一个迭代器,但那是另一个讨论。

+2

你知道'next'每次调用都会创建一个新的迭代器吗? – mcarton

正如评论中所提到的,你的迭代器缺少一个关键的状态:在迭代中有多远,它是。每次调用next时,它都会从头开始构造另一个迭代器并获取第一个元素。

这里有一个降低例如:

struct ListZipper { 
    focus: Option<u8>, 
} 

impl Iterator for ListZipper { 
    type Item = u8; 

    fn next(&mut self) -> Option<Self::Item> { 
     self.focus.iter().next().cloned() 
    } 
} 

fn main() { 
    let lz = ListZipper { focus: Some(42) }; 
    let head: Vec<_> = lz.take(5).collect(); 
    println!("{:?}", head); // [42, 42, 42, 42, 42] 
} 

我意识到我可能不希望ListZipper自己是一个迭代器,但那是另一个讨论。

不,这真的不是^ _ ^。你需要以某种方式改变被迭代的东西,以便它可以改变,并为每个后续的调用有不同的值。

如果你想回到现有的迭代器和迭代器适配器的组合,是指Correct way to return an Iterator?的说明。

否则,您需要在通话过程中以某种方式改变ListZippernext

impl Iterator for ListZipper { 
    type Item = Tile; 

    fn next(&mut self) -> Option<Self::Item> { 
     if let Some(v) = self.left.pop_front() { 
      return Some(v); 
     } 

     if let Some(v) = self.focus.take() { 
      return Some(v); 
     } 

     if let Some(v) = self.right.pop_front() { 
      return Some(v); 
     } 

     None 
    } 
} 

更简洁:

impl Iterator for ListZipper { 
    type Item = Tile; 

    fn next(&mut self) -> Option<Self::Item> { 
     self.left.pop_front() 
      .or_else(|| self.focus.take()) 
      .or_else(|| self.right.pop_front()) 
    } 
} 

请注意,您PartialEq实现似乎是一样的自动派生的...

use std::collections::VecDeque; 

type Tile = u8; 

#[derive(Debug, Clone, PartialEq)] 
pub struct ListZipper { 
    pub focus: Option<Tile>, 
    pub left: VecDeque<Tile>, 
    pub right: VecDeque<Tile>, 
} 

impl Iterator for ListZipper { 
    type Item = Tile; 

    fn next(&mut self) -> Option<Self::Item> { 
     self.left.pop_front() 
      .or_else(|| self.focus.take()) 
      .or_else(|| self.right.pop_front()) 
    } 
} 

fn main() { 
    let lz = ListZipper { 
     focus: Some(42), 
     left: vec![1, 2, 3].into(), 
     right: vec![97, 98, 99].into(), 
    }; 

    let head: Vec<_> = lz.take(5).collect(); 

    println!("{:?}", head); 
} 
+0

非常感谢您的详细解答。现在很清楚。感谢您对“PartialEq”的评论。 – svdc