Изучаю Rust, решаю всякие задачки. Понадобились простые числа, решил создать вспомогательный «класс» для их генерации. Идея в том, чтобы генерировать последовательность путём стандартного итерирования. Вроде решил, но как-то сложно получилась, какие-то лайфтаймы, мутабельности, такое ощущение, что перемудрил и юзать не очень удобно: нельзя просто написать for p in primes { ... }, только for p in &mut primes { ... }, можно ли как-то получше сделать? Если что, primes должен быть потенциально многоразовый.
fn main() {
let mut primes = Primes::new();
let mut counter = 0;
for p in &mut primes {
println!("{}", p);
counter += 1;
if counter > 10 {
break;
}
}
}
struct Primes {
cache: Vec<u64>,
}
impl Primes {
fn new() -> Primes {
Primes { cache: vec!(2, 3) }
}
}
impl<'a> IntoIterator for &'a mut Primes {
type Item = u64;
type IntoIter = PrimesIterator<'a>;
fn into_iter(self) -> PrimesIterator<'a> {
PrimesIterator { cache: &mut self.cache, cache_index: 0 }
}
}
struct PrimesIterator<'a> {
cache: &'a mut Vec<u64>,
cache_index: usize,
}
impl<'a> Iterator for PrimesIterator<'a> {
type Item = u64;
fn next(&mut self) -> Option<u64> {
let result: u64;
if self.cache_index < self.cache.len() {
result = self.cache[self.cache_index];
} else {
let mut n = self.cache[self.cache_index - 1] + 2;
loop {
let mut i = 0;
let is_prime = loop {
let p = self.cache[i];
if n % p == 0 {
break false;
}
if p * p > n {
break true;
}
i += 1;
};
if is_prime {
break;
}
n += 2;
}
self.cache.push(n);
result = n;
}
self.cache_index += 1;
Some(result)
}
}