是否可以在不创建特殊迭代器的情况下逐步逐步使用不同的量



在c中,一个for loop具有一个可选的增量部分,我有时会在Rust中错过:

for (uint i = 0; i < max; i = step_function(i, j, k)) {
    /* many lines of code! */
}

这可以用生锈写为:

let mut i: u32 = 0;
while (i < max) {
    // 
    // many lines of code! 
    //
    i = step_function(i, j, k);
}

...但是,如果continue存在于"许多代码行" 中的某个地方,这将引入错误。我的个人偏爱也是将增量保持在循环的顶部。

没有创建特殊的迭代器来处理此操作,是否有一种方法可以更紧密地匹配C样式?

由"特殊迭代器",我的意思是不必定义迭代仪类型和for循环外的方法。

虽然它似乎是人为的要求,但必须定义一个用于单一用途的迭代器 - 在阅读和编写代码时添加了一些开销。

尽管 @kennytm的答案显示了可重复使用的StepByFn迭代器如何工作,但使用闭合添加了对代码的一些约束。

如果您可以导入外部板条箱,则应使用itertools::iterate

extern crate itertools;
use itertools::iterate;
fn main() {
    for i in iterate(0, |i| 2*i + 3).take_while(|i| *i < 100) {
        println!("{}", i);
        // 0 3 9 21 45 93
    }
}

,如果您是真的缺少循环的C风格,则可以使用cfor板条箱:

#[macro_use] extern crate cfor;
fn main() {
    cfor!{ let mut i = 0; i < 100; i = 2*i + 3; {
        println!("{}", i);
        // 0 3 9 21 45 93
    }}
}

如果您仅限于使用标准库,则创建特殊的迭代器将是最惯用的方式。

fn main() {
    for i in StepByFn::new(0, 100, |i| 2*i + 3) {
        println!("{}", i);
        // 0 3 9 21 45 93
    }
}
struct StepByFn<T, F> {
    begin: T,
    end: T,
    step: F,
}
impl<T, F: FnMut(&T) -> T> StepByFn<T, F> {
    pub fn new(begin: T, end: T, step: F) -> StepByFn<T, F> {
        StepByFn { begin, end, step }
    }
}
impl<T: PartialOrd, F: FnMut(&T) -> T> Iterator for StepByFn<T, F> {
    type Item = T;
    fn next(&mut self) -> Option<T> {
        if self.begin >= self.end {
            return None;
        }
        let next = (self.step)(&self.begin);
        let prev = std::mem::replace(&mut self.begin, next);
        Some(prev)
    }
}

也可以使用repeat().scan()创建一个内联迭代器,但它非常丑陋,并且不太表达意图

use std::iter::repeat;
fn main() {
    for i in repeat(()).scan(0, |i, ()| { 
        let old = *i; 
        *i = 2*old + 3; 
        if old < 100 { Some(old) } else { None } 
    }) {
        println!("{}", i);
        // 0 3 9 21 45 93
    }
}

相关内容

  • 没有找到相关文章

最新更新