我正在尝试实现一个可以无限迭代的结构。可以将其类比为自然数。有一个限制:它不能实现Copy
特性,因为该结构包含了一个String
字段。
我还实现了Iterable
特性和它唯一的成员函数fn next(&mut self) -> Option<Self::Item>
。
目前,我有以下代码来遍历我的结构的前10个项:
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
结构遍历我的结构体,像这样:
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);
}
现在如果我们运行示例,将会得到两个具有相同hash
的Game
结构体,然而预期的行为是第一个g
将具有等于SHA256(game.hash)的hash
,而下一个g
的哈希将会是SHA256(SHA256(game.hash))。当我调用.next()
时它可以正常工作。
GameIter
,并将其提供给用户,例如game.iter()
。 任何实现了Iterator
接口的结构体都可以在for ... in ...
表达式中使用,如果你想限制迭代次数,只需使用take
。 - Caionext
函数... - Matthieu M.Iterator
和IntoIter
有什么问题吗? - Matthieu M.loop
和for
循环中表现不同而导致的挫败感。我的上面使用loop
的示例的工作方式与for
的描述行为非常相似,而我无法获得预期的行为并且无法捕捉到问题所在,因此我认为问题出在我如何实现迭代器特质上。 - Vladimir Ignatev