如何在Rust中正确实现Iterable结构? [英] How to properly implement Iterable structure in Rust?
问题描述
我正在尝试实现可以无限迭代的结构.认为它是一个自然数.我有一个局限性:它不能实现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(¶m);
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);
}
现在,如果我们运行示例,我们将获得两个具有相同hash
的Game
结构,而预期的行为是第一个g
的hash
等于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_mut
,iter
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个新类型IterMut
和Iter
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屋!