Đối với tôi, dường như cho đến khi .step_by
phương thức này được ổn định, người ta có thể dễ dàng thực hiện những gì bạn muốn với một Iterator
( Range
dù sao thì đó cũng là điều thực sự):
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);
}
}
Nếu một người cần lặp lại nhiều phạm vi thuộc các loại khác nhau, mã có thể được tạo chung như sau:
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);
}
}
Tôi sẽ giao nó cho bạn để loại bỏ kiểm tra giới hạn trên để tạo cấu trúc kết thúc mở nếu cần một vòng lặp vô hạn ...
Ưu điểm của phương pháp này là hoạt động với for
đường và sẽ tiếp tục hoạt động ngay cả khi các tính năng không ổn định có thể sử dụng được; Ngoài ra, không giống như cách tiếp cận loại bỏ đường bằng cách sử dụng tiêu chuẩn Range
s, nó không làm mất hiệu quả bởi nhiều .next()
cuộc gọi. Nhược điểm là phải mất một vài dòng mã để thiết lập trình lặp, vì vậy có thể chỉ đáng giá đối với mã có nhiều vòng lặp.