পাঠ ১৩.২

Iterator দিয়ে item-গুলো process করা

Processing a Series of Items with Iterators

Iterator pattern — sequence-এর প্রতিটা item-এ এক এক করে কিছু করা। Rust-এ iterator lazy — যতক্ষণ পর্যন্ত consume না করছ, কিছু হবে না।

Iterator তৈরি ও use

fn main() {
    let v1 = vec![1, 2, 3];

    let v1_iter = v1.iter();
}

এই code-এ কিছুই হচ্ছে না — iterator তৈরি, কিন্তু consume হয়নি।

fn main() {
    let v1 = vec![1, 2, 3];

    let v1_iter = v1.iter();

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

for loop iterator-কে consume করছে — প্রতিটা iteration-এ একটা item।

Iterator trait এবং next method

pub trait Iterator {
    type Item;

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

    // অন্য method-গুলোর default implementation আছে
}

Item = এই iterator কী return করবে। next = একটামাত্র required method — পরের item-কে Some-এ wrap করে দেয়; শেষ হলে None

#[test]
fn iterator_demonstration() {
    let v1 = vec![1, 2, 3];

    let mut v1_iter = v1.iter();

    assert_eq!(v1_iter.next(), Some(&1));
    assert_eq!(v1_iter.next(), Some(&2));
    assert_eq!(v1_iter.next(), Some(&3));
    assert_eq!(v1_iter.next(), None);
}

লক্ষ্য — v1_iter mutnext internal state বদলায় (কোথায় আছ track করে)। For loop ভেতরে এটা automatic।

iter() immutable reference-এর iterator (&i32)। আরও আছে:

  • iter() — immutable reference।
  • into_iter() — ownership নেয়, owned value return।
  • iter_mut() — mutable reference।

Consuming adapter

যেসব method next call করে iterator শেষ পর্যন্ত ব্যবহার করে — যেমন sum:

#[test]
fn iterator_sum() {
    let v1 = vec![1, 2, 3];

    let v1_iter = v1.iter();

    let total: i32 = v1_iter.sum();

    assert_eq!(total, 6);
}

sum iterator ownership নেয় — তাই পরে v1_iter ব্যবহার করা যাবে না।

Iterator adapter — অন্য iterator return করে

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

    v1.iter().map(|x| x + 1);
}

এই code warning দেবে — iterator lazy, এখনই কিছু হচ্ছে না। .collect() দিয়ে consume:

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

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

    assert_eq!(v2, vec![2, 3, 4]);
}

adapter chain readable — যেমন .iter().map(...).filter(...).collect()

Closure দিয়ে environment capture

#[derive(PartialEq, Debug)]
struct Shoe {
    size: u32,
    style: String,
}

fn shoes_in_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
    shoes.into_iter().filter(|s| s.size == shoe_size).collect()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn filters_by_size() {
        let shoes = vec![
            Shoe { size: 10, style: String::from("sneaker") },
            Shoe { size: 13, style: String::from("sandal") },
            Shoe { size: 10, style: String::from("boot") },
        ];

        let in_my_size = shoes_in_size(shoes, 10);

        assert_eq!(
            in_my_size,
            vec![
                Shoe { size: 10, style: String::from("sneaker") },
                Shoe { size: 10, style: String::from("boot") },
            ]
        );
    }
}
  • into_iter() — vec-এর ownership নিয়ে owned value-র iterator।
  • .filter(closure) — closure true হলে item রাখে।
  • Closure shoe_size capture করছে — outer scope থেকে।
  • .collect() — final Vec।

এই পাঠ থেকে যা শিখলে

  • Iterator lazy — consume না করলে কিছুই হয় না।
  • Iterator trait এক method — next() -> Option<Item>
  • iter / into_iter / iter_mut — borrow level আলাদা।
  • Consuming adapter (sum, collect) iterator শেষ করে; iterator adapter (map, filter) নতুন iterator return করে।
  • filter, map ইত্যাদি closure নেয় — যা environment capture করতে পারে।