← Back to Rust Course | Chapter 14: Closures, Iterators & Async | Lesson 4 of 6

Custom Iterators बनाना

आप अपने खुद के data के लिए अपनी खुद की तरह का list-walker design कर सकते हैं, इसे बिल्कुल सिखाते हुए कि items एक समय में एक कैसे दें।
Syntax
rust
struct Name {
    state: Type,
}

impl Iterator for Name {
    type Item = Type;
    fn next(&mut self) -> Option<Type> {
        // return Some(value) or None
    }
}

A Custom Iterator Struct

एक custom iterator आमतौर पर एक छोटा struct होता है जो अगला item compute करने के लिए ज़रूरी किसी भी state को रखता है, इसके ऊपर Iterator implemented होने के साथ।

उदाहरण: A Custom Iterator Struct

markup
// Define a struct `Evens` to group related fields together
struct Evens {
    current: i32,
    max: i32,
}

// Implement the `Iterator` trait for `Evens`
impl Iterator for Evens {
    type Item = i32;
    // Define the function `next` taking `self` and returning a `Option<i32>`
    fn next(&mut self) -> Option<i32> {
        // Check whether `self.current > self.max`
        if self.current > self.max {
            None
        // Otherwise, run this branch
        } else {
            // Declare an immutable variable `value`, set to `self.current`
            let value = self.current;
            self.current += 2;
            Some(value)
        }
    }
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `evens`, set to `Evens { current: 0, max: 8 }`
    let evens = Evens { current: 0, max: 8 };
    // Loop over `evens`, binding each item to `n`
    for n in evens {
        // Print "{}" to the console, substituting in `n` (with a trailing newline)
        println!("{}", n);
    }
}

Using Adapters on a Custom Iterator

एक बार Iterator implement हो जाए, एक custom type अपने आप adapter methods की पूरी range support करता है, आपको बिल्कुल वैसे ही pipelines बनाने देते हुए जैसे आप एक built-in iterator पर बनाते।

उदाहरण: Using Adapters on a Custom Iterator

markup
// Define a struct `Evens` to group related fields together
struct Evens {
    current: i32,
    max: i32,
}

// Implement the `Iterator` trait for `Evens`
impl Iterator for Evens {
    type Item = i32;
    // Define the function `next` taking `self` and returning a `Option<i32>`
    fn next(&mut self) -> Option<i32> {
        // Check whether `self.current > self.max`
        if self.current > self.max {
            None
        // Otherwise, run this branch
        } else {
            // Declare an immutable variable `value`, set to `self.current`
            let value = self.current;
            self.current += 2;
            Some(value)
        }
    }
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `total` (an integer), set to `Evens { current: 0, max: 10 }.map(|n| n * 2).sum()`
    let total: i32 = Evens { current: 0, max: 10 }.map(|n| n * 2).sum();
    // Print "Total: {}" to the console, substituting in `total` (with a trailing newline)
    println!("Total: {}", total);
}

Implementing IntoIterator for a Collection

किसी custom collection struct के लिए IntoIterator implement करना इसे सीधे एक for loop के साथ उपयोग होने देता है, एक inner iterator type को delegate करते हुए।

उदाहरण: Implementing IntoIterator for a Collection

markup
// Define a struct `Bag` to group related fields together
struct Bag {
    items: Vec<i32>,
}

// Implement the `IntoIterator` trait for `Bag`
impl IntoIterator for Bag {
    type Item = i32;
    type IntoIter = std::vec::IntoIter<i32>;
    // Define the function `into_iter` taking `self` and returning a `Self::IntoIter`
    fn into_iter(self) -> Self::IntoIter {
        self.items.into_iter()
    }
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `bag`, set to `Bag { items: vec![10, 20, 30] }`
    let bag = Bag { items: vec![10, 20, 30] };
    // Loop over `bag`, binding each item to `item`
    for item in bag {
        // Print "{}" to the console, substituting in `item` (with a trailing newline)
        println!("{}", item);
    }
}

Ensuring the Iterator Terminates

एक सही implemented iterator को आखिरकार None return करना चाहिए; नहीं तो, इसे पूरी तरह consume करने वाला कोई भी code (जैसे .collect() या .sum()) हमेशा के लिए loop करेगा।

उदाहरण: Ensuring the Iterator Terminates

markup
// Define a struct `Countdown` to group related fields together
struct Countdown(u32);

// Implement the `Iterator` trait for `Countdown`
impl Iterator for Countdown {
    type Item = u32;
    // Define the function `next` taking `self` and returning a `Option<u32>`
    fn next(&mut self) -> Option<u32> {
        // Check whether `self.0 == 0`
        if self.0 == 0 {
            None
        // Otherwise, run this branch
        } else {
            self.0 -= 1;
            Some(self.0 + 1)
        }
    }
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `collected` (a `Vec<u32>`), set to `Countdown(5).collect()`
    let collected: Vec<u32> = Countdown(5).collect();
    // Print "{:?}" to the console, substituting in `collected` (with a trailing newline)
    println!("{:?}", collected);
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
आम गलतियां
  1. किसी collection struct के लिए IntoIterator implement करना भूल जाना अगर आप चाहते हैं कि यह सीधे एक for loop में काम करे।
  2. next() को इस तरह लिखना जो कभी None return नहीं करता, .collect() जैसे किसी consuming method को हमेशा के लिए loop करने का कारण बनते हुए।
  3. Common adapter logic को manually फिर से implement करना बजाय सिर्फ एक बार Iterator implement करके built-in adapter methods reuse करने के।
चैप्टर सारांश
  • किसी custom struct के लिए Iterator implement करने के लिए type Item और next() method define करना ज़रूरी है।
  • IntoIterator implement करना किसी custom collection type को सीधे एक for loop में उपयोग होने देता है।
  • एक well-behaved iterator को आखिरकार next() से None return करना चाहिए, नहीं तो .collect() जैसे consumers हमेशा के लिए loop करेंगे।
  • Custom iterators अपने आप iterator adapter methods की पूरी standard library तक access पाते हैं।
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.