如何在Rust中正确实现Iterable结构? [英] How to properly implement Iterable structure in Rust?

查看:77
本文介绍了如何在Rust中正确实现Iterable结构?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现可以​​无限迭代的结构.认为它是一个自然数.我有一个局限性:它不能实现Copy特征,因为该结构包含一个String字段.

I'm trying to implement a structure that can be infinitely iterated. Think it like a natural number. I have a limitation: it can't implement Copy trait because the structure contains a String field.

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

I've also implemented an Iterable trait and its only member fn next(&mut self) -> Option<Self::Item>.

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

Currently, I have the following code to iterate over the first 10 items of my structure:

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构造遍历我的结构的能力,如下所示:

I'd like to give to users of my crate the ability to iterate over my struct using for in construction, like this:

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

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

Is it possible at all? How can I achieve this? How to make my code better and what I have to do with my struct?

迭代器实现:

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结构,而预期的行为是第一个ghash等于SHA256(game.hash),下一个g的哈希将为SHA256(SHA256(game.hash)).当我呼叫.next()时,它可以正常工作.

Now if we run example, we will get two Game structs with same hash, while expected behavior is that the first g will have hash equal to SHA256(game.hash) and the next g's hash will be SHA256(SHA256(game.hash)). It works properly when I call .next().

推荐答案

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

In the Rust iterators actually can be divided into 2 categories. Iterators which own the struct, thus can be created using .into_iter() which consumes self.

以及在不消耗结构的情况下对结构进行迭代的迭代器.通常可以使用.iter.iter_mut()

And iterators that iterate over structure without consuming it. They can be created be usually created using: .iter, .iter_mut()

有关更多信息,请参见相关问题:有什么区别在iter和into_iter之间? 和文档:这三种迭代形式

For more information see related question: What is the difference between iter and into_iter? And documention: The three forms of iteration

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

To create iterator you should implement either IntoIterator trait, which will transform your structure into iterator or write functions which will create iterator: iter_mut, iter

pub fn iter_mut(&mut self) -> IterMut<T>

pub fn iter(&self) -> Iter<T>

因此,按照惯例,您需要2个新类型IterMutIter

So by convention you need 2 new types IterMut and Iter

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> {
        /* ... */
    }
}

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

They usually contain in them reference to the parent structure. For example for linked list it can be current node (which is updated every iteration). For array-like structures it can be index and reference to the parent, so index will incremented every time and element accessed using index operator and etc..

这篇关于如何在Rust中正确实现Iterable结构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆