Tampak bagi saya bahwa sampai .step_by
metode dibuat stabil, seseorang dapat dengan mudah mencapai apa yang Anda inginkan dengan Iterator
(yang sebenarnya adalah apa Range
):
struct SimpleStepRange(isize, isize, isize);
impl Iterator for SimpleStepRange {
type Item = isize;
#[inline]
fn next(&mut self) -> Option<isize> {
if self.0 < self.1 {
let v = self.0;
self.0 = v + self.2;
Some(v)
} else {
None
}
}
}
fn main() {
for i in SimpleStepRange(0, 10, 2) {
println!("{}", i);
}
}
Jika seseorang perlu mengulang beberapa rentang dari tipe yang berbeda, kode dapat dibuat umum sebagai berikut:
use std::ops::Add;
struct StepRange<T>(T, T, T)
where for<'a> &'a T: Add<&'a T, Output = T>,
T: PartialOrd,
T: Clone;
impl<T> Iterator for StepRange<T>
where for<'a> &'a T: Add<&'a T, Output = T>,
T: PartialOrd,
T: Clone
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
if self.0 < self.1 {
let v = self.0.clone();
self.0 = &v + &self.2;
Some(v)
} else {
None
}
}
}
fn main() {
for i in StepRange(0u64, 10u64, 2u64) {
println!("{}", i);
}
}
Saya akan menyerahkan kepada Anda untuk menghilangkan pemeriksaan batas atas untuk membuat struktur ujung terbuka jika diperlukan loop tak terbatas ...
Keuntungan dari pendekatan ini adalah berfungsi dengan for
sugaring dan akan terus berfungsi bahkan ketika fitur yang tidak stabil menjadi dapat digunakan; juga, tidak seperti pendekatan de-sugared yang menggunakan standar Range
, ia tidak kehilangan efisiensi dengan beberapa .next()
panggilan. Kekurangannya adalah dibutuhkan beberapa baris kode untuk mengatur iterator sehingga mungkin hanya sepadan untuk kode yang memiliki banyak loop.