สำหรับฉันแล้วดูเหมือนว่าจนกว่า.step_by
วิธีการนี้จะมีเสถียรภาพเราสามารถบรรลุสิ่งที่คุณต้องการได้อย่างง่ายดายด้วยIterator
(ซึ่งก็คือสิ่งที่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);
}
}
หากจำเป็นต้องวนซ้ำหลายช่วงของประเภทต่างๆโค้ดสามารถสร้างเป็นแบบทั่วไปได้ดังนี้:
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);
}
}
ฉันจะปล่อยให้คุณกำจัดการตรวจสอบขอบเขตด้านบนเพื่อสร้างโครงสร้างปลายเปิดหากต้องการลูปที่ไม่มีที่สิ้นสุด ...
ข้อดีของวิธีนี้คือใช้ได้กับการทำfor
น้ำตาลและจะยังคงทำงานต่อไปแม้ว่าจะใช้งานฟีเจอร์ที่ไม่เสถียรได้ก็ตาม ยังแตกต่างจากวิธีการลดน้ำตาลโดยใช้มาตรฐานRange
s คือไม่สูญเสียประสิทธิภาพจากการ.next()
โทรหลายครั้ง ข้อเสียคือต้องใช้โค้ดสองสามบรรทัดในการตั้งค่าตัววนซ้ำดังนั้นอาจคุ้มค่าสำหรับโค้ดที่มีการวนซ้ำมาก ๆ