如何在Rust中实现Haskell风格的惰性素数迭代器并解决编译报错
错误原因
- 你遇到的E0507错误本质是
Iterator::filter方法会消费原迭代器,需要获得原迭代器的所有权,而self.nums是可变引用&mut self的字段,Rust不允许直接将字段值移出结构体,会导致结构体出现临时的非法状态。 - 第二种使用
borrow_mut的思路不符合类型匹配要求,属于方向错误,不需要继续尝试。
修复方案
核心是借助std::mem::replace先将原迭代器从self.nums中置换出来,拿到所有权后再做filter操作,最后把新生成的迭代器赋值回self.nums即可。
修改后的可运行代码如下:
use std::mem; // 优化为返回静态分发的迭代器,避免堆分配开销 fn primes() -> impl Iterator<Item = usize> { Primes::new() } struct Primes { nums: Box<dyn Iterator<Item = usize>>, } impl Primes { fn new() -> Self { Primes { nums: Box::new(2..) } } } impl Iterator for Primes { type Item = usize; fn next(&mut self) -> Option<usize> { // 置换出原有迭代器,拿到所有权 let mut old_nums = mem::replace(&mut self.nums, Box::new(std::iter::empty())); let prime = old_nums.next().unwrap(); // 生成带过滤规则的新迭代器赋值回去 self.nums = Box::new(old_nums.filter(move |&n| !divides(prime, n))); Some(prime) } } pub fn divides(d: usize, n: usize) -> bool { n % d == 0 } // 测试示例:打印前10个素数 fn main() { for p in primes().take(10) { println!("{}", p); } }
内容的提问来源于stack exchange,提问作者hkBst
相关产品推荐
相关产品推荐

