【问题标题】:How to properly implement Iterable structure in Rust? [duplicate]如何在 Rust 中正确实现 Iterable 结构? [复制]
【发布时间】:2019-06-20 03:33:17
【问题描述】:

我正在尝试实现一个可以无限迭代的结构。把它想象成一个自然数。我有一个限制:它无法实现 Copy 特征,因为该结构包含 String 字段。

我还实现了一个 Iterable 特征及其唯一成员 fn next(&mut self) -> Option<Self::Item>

目前,我有以下代码来迭代我的结构的前 10 项:

let mut counter = 0;
let mut game:Option<Game> = Game::new(&param);
loop {
    println!("{:?}", game); 

    game = g.next();
    counter = counter + 1;
    if counter > 10 { break; }
}

我想让crate 的用户能够使用for in 构造迭代我的结构,如下所示:

for next_game in game {
  println!("{:?}", next_game);
} 

有可能吗?我怎样才能做到这一点?如何使我的代码更好以及我与我的结构有什么关系?

迭代器实现:

pub struct Game {
    /// The game hash
    pub hash: Vec<u8>
}

impl Iterator for Game {
    type Item = Game;

    fn next(&mut self) -> Option<Self::Item> {
        let mut hasher = Sha256::new();
        hasher.input(&hex::encode(&self.hash)); // we need to convert the hash into string first
        let result = hasher.result().to_vec();

        Some(Game {
            hash: result
        })
    }
}

示例:for 的破坏行为

let mut game:Game = Game::new(&s).unwrap();
for g in game.take(2) {
    println!("{}", g);
}

现在,如果我们运行示例,我们将得到两个具有相同 hashGame 结构,而预期的行为是第一个 g 将具有等于 SHA256(game.hash) 的 hash 和下一个 @ 987654338@ 的哈希值为 SHA256(SHA256(game.hash))。当我拨打.next()时,它可以正常工作。

【问题讨论】:

  • 大多数人所做的就是创建一个新结构,例如GameIter,然后像game.iter() 一样将其提供给用户。任何实现Iterator 的结构都可以在for ... in ... 表达式中使用,如果您想限制迭代次数,只需使用take
  • 如果您提供了Game 结构的实现,这个问题会更加清晰。
  • @AndreyTyukin:next 函数...
  • 实现IteratorIntoIter有什么问题?

标签: rust iterator


【解决方案1】:

在 Rust 迭代器中实际上可以分为 2 类。拥有该结构的迭代器,因此可以使用消耗self.into_iter() 创建。

以及迭代结构而不消耗它的迭代器。通常可以使用以下方式创建它们:.iter.iter_mut()

欲了解更多信息,请参阅相关问题:What is the difference between iter and into_iter? 和文档:The three forms of iteration

要创建迭代器,您应该实现IntoIterator trait,它将您的结构转换为迭代器或编写将创建迭代器的函数:iter_mutiter

pub fn iter_mut(&amp;mut self) -&gt; IterMut&lt;T&gt;

pub fn iter(&amp;self) -&gt; Iter&lt;T&gt;

所以按照惯例,您需要 2 个新类型 IterMutIter

impl Iterator for Iter {
    type Item = /* ... */;
    fn next(&mut self) -> Option<Self::Item> {
        /* ... */
    }
}

impl Iterator for IterMut {
    type Item = &mut /* ... */;
    fn next(&mut self) -> Option<Self::Item> {
        /* ... */
    }
}

它们通常包含对父结构的引用。例如,对于链表,它可以是当前节点(每次迭代都会更新)。对于类似数组的结构,它可以是索引和对父级的引用,因此索引每次都会递增,并且使用索引运算符等访问元素。

【讨论】:

    猜你喜欢
    • 2020-01-11
    • 1970-01-01
    • 1970-01-01
    • 2015-10-29
    • 2021-05-15
    • 1970-01-01
    • 1970-01-01
    • 2017-02-16
    • 2016-09-05
    相关资源
    最近更新 更多