使用Iter::find时如何对每个结构体调用可变方法?
问题原因
语法层面错误
iter_mut() 生成的迭代器元素类型为 &mut Game,而 Iterator::find 方法要求传入的谓词闭包接收的是迭代器元素的不可变引用,也就是你拿到的 game 参数实际是 &&mut Game 类型。你无法通过一层不可变引用调用需要可变借用的 play 方法,因此触发借用检查报错。
逻辑层面不合理
find 的设计语义是无副作用的查找操作,仅用来判断元素是否符合条件,不应该在谓词内部修改元素状态。你当前的写法会导致遍历过程中,只有排在前面的游戏会被执行 play 操作,一旦某个游戏获胜就终止遍历,后面的游戏永远不会在本轮获得执行机会,和常规的「多游戏每轮各走一步」的逻辑不符。
解决方法
方法1:保持原有逻辑的语法修正
如果你确实需要「找到第一个执行play后获胜的游戏、其余游戏本轮不执行」的逻辑,可以通过解引用拿到可变引用:
loop { if let Some(winner) = games .iter_mut() .find(|game| { let play = rng.gen_range(1..=10); // 两次解引用获取可变实例,调用play方法 (**game).play(play) }) { println!("Winner!: {:?}", winner); break; // 原代码会死循环,建议找到获胜者后退出 } }
也可以通过模式匹配直接在闭包参数中提取可变引用:
.find(|&mut ref mut game| { let play = rng.gen_range(1..=10); game.play(play) })
方法2:更符合语义的惯用实现
如果你需要每轮给所有游戏各执行一次play操作,直到有游戏获胜,直接用循环遍历即可,完全规避借用问题,也更符合逻辑:
loop { for game in games.iter_mut() { let play = rng.gen_range(1..=10); if game.play(play) { println!("Winner!: {:?}", game); return; } } }
内容的提问来源于stack exchange,提问作者Martin Cowie
相关产品推荐
相关产品推荐

