Iterators

Iterator pattern cho phép bạn thực hiện một số tác vụ trên từng phần tử một cách tuần tự. Một iterator chịu trách nhiệm về logic của việc lặp qua từng phần tử và xác định khi nào chuỗi đã kết thúc. Khi bạn sử dụng iterators, bạn không cần phải tái hiện lại logic đó một lần nữa.

Trong Rust, iterators là lazy, nghĩa là chúng không có tác dụng gì cho đến khi bạn gọi các phương thức consume iterator (e.g. sum, count, ...).

#![allow(unused)]
fn main() {
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter(); // lazy

for val in v1_iter {
    println!("Got: {val}");
}
// Got: 1
// Got: 2
// Got: 3
}

The Iterator Trait and the next Method

Tất cả iterators được implement một trait tên là Iterator được định nghĩa trong standard library. Định nghĩa của trait trông như sau:

#![allow(unused)]
fn main() {
pub trait Iterator {
    type Item;

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

    // methods with default implementations elided
}
}

Consume the Iterator

Phương thức gọi next được gọi là consuming adaptors.

#![allow(unused)]
fn main() {
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter(); // lazy

let total: i32 = v1_iter.sum(); // Consume
println!("Total: {}", &total);  // Total: 6
}

v1_iter không thể sử dụng bởi vì sum đã takes ownership của iterator.

Produce Other Iterators

Iterator adaptors là các phương thức được định nghĩa trên trait Iterator không consume iterator. Thay vào đó, chúng produce ra các iterator khác bằng cách thay đổi một ít từ iterator gốc.

#![allow(unused)]
fn main() {
let v1: Vec<i32> = vec![1, 2, 3];

v1.iter().map(|x| x + 1); // new iter
}
#![allow(unused)]
fn main() {
let v1: Vec<i32> = vec![1, 2, 3];

let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();

println!("{:?}", v2); // [2, 3, 4]
}

References