问题
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.
I've also implemented an Iterable
trait and its only member fn next(&mut self) -> Option<Self::Item>
.
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; }
}
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?
Iterator implementation:
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
})
}
}
Example: broken behavior with for
let mut game:Game = Game::new(&s).unwrap();
for g in game.take(2) {
println!("{}", g);
}
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()
.
回答1:
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
.
And iterators that iterate over structure without consuming it. They can be created be usually created using: .iter
, .iter_mut()
For more information see related question: What is the difference between iter and into_iter? And documention: The three forms of iteration
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>
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..
来源:https://stackoverflow.com/questions/54379841/how-to-properly-implement-iterable-structure-in-rust