Rust--Iterators

216 阅读1分钟

什么是Iterators?

Iterators允许我们在一系列的值上按顺序执行某个任务

// Iterator例子

fn main() {
    let v1 = vec![1, 2, 3];
    let v1_iter = v1.iter(); // nothing happens, due to lazy nature


    // for loop takes ownership of iterators
    for val in v1_iter {
        println!("Got: {}", val);
    }
    
    // 等同于
    for i in 0..v1.len() {
        println!("Got: {}", v1[i]);
    }

}



// 由于 for 循环会拿走iterator的拥有权,所以之后无法再使用v1_iter
// 下面的用法编译不通过

fn main() {
    let v1 = vec![1, 2, 3];
    let v1_iter = v1.iter(); // nothing happens, due to lazy nature


    for val in v1_iter {
        println!("Got: {}", val);
    }

    println!("{:?}", v1_iter);
}

编译提示:

error[E0382]: borrow of moved value: `v1_iter`
   --> src/main.rs:10:22
    |
3   |     let v1_iter = v1.iter(); // nothing happens, due to lazy nature
    |         ------- move occurs because `v1_iter` has type `std::slice::Iter<'_, i32>`, which does not implement the `Copy` trait
...
6   |     for val in v1_iter {
    |                -------
    |                |
    |                `v1_iter` moved due to this implicit call to `.into_iter()`
    |                help: consider borrowing to avoid moving into the for loop: `&v1_iter`
...
10  |     println!("{:?}", v1_iter);
    |                      ^^^^^^^ value borrowed here after move
    |

How, 如何实现Iterators?

rust中,是通过trait来实现的,每个Iterator都需要实现类似如下的trait



pub trait Iterator {
    type Item;

    fn next(&mut self) -> Option<Self::Item>;
}

通过一个例子,斐波那契数列来展示:

fibonacci数列的定义是,前两个数字是1,第三个数字开始,每个数字都是前面两个数字之和, 即 1,1,2,3,5,8,13 ...

struct Fibonacci {
    curr: u32,
    next: u32,
}

// 实现Iterator trait
// Iterator trait中还有其他方法,留给我们需要实现的,只有next()
impl Iterator for Fibonacci {
    type Item = u32;
    fn next(&mut self) -> Option<Self::Item> {
        let new_next = self.curr + self.next;
        self.curr = self.next;
        self.next = new_next;

        Some(self.curr)
    }
}


fn main() {
    let mut fib = Fibonacci {
        curr: 1,
        next: 1,
    };

    for _ in 0..10 {
        println!("{:?}", fib.curr);
        fib.next();  //实现之后,可以调用.next()
    }
}