Thuta Learning
ရှာဖွေရန်
Rust
AdvancedProgrammingbeginner

Closures နှင့် Iterators

ဒီခန်းပြီးရင် ဘာတတ်သွားမလဲ

  • Closures နှင့် Iterators concept ကို နားလည်ရှင်းပြနိုင်ရန်
  • နမူနာ Rust code ကို ကိုယ်တိုင် run ပြီး output စစ်နိုင်ရန်
  • Tutorial Platform project နှင့် production scenario တွင် မှန်ကန်စွာအသုံးချနိုင်ရန်

နားလည်ထားရမယ့် အချက်

Closure ဆိုတာ anonymous function တစ်မျိုးဖြစ်ပြီး named function နှင့် ကွာတဲ့ အချက်ကတော့ closure က define လုပ်ထားတဲ့ scope ထဲက variable တွေကို "capture" လုပ်နိုင်တာပါ—`|word| word.len() > min_length` လို closure ထဲက `min_length` ကို enclosing scope ကနေ ကိုးကားနိုင်ပါတယ်။ Closure က variable ကို capture လုပ်တဲ့နည်းလမ်း သုံးမျိုးရှိပါတယ်—borrow (`&T`, default, read-only access), mutable borrow (`&mut T`), move (ownership take, `move` keyword ဖြင့် explicit)—ဒီ choice ကို Lesson 6/7 ရဲ့ ownership rule အတိုင်းပဲ compiler က automatically ဆုံးဖြတ်ပေးပါတယ်။ Iterator ဆိုတာ collection ကို element တစ်ခုချင်းစီ traverse ဖြစ်စေတဲ့ lazy sequence ဖြစ်ပြီး `map` (transform), `filter` (select), `collect` (final collection အဖြစ် materialize) လို adapter method တွေက chain ဖြစ်ပြီး lazy evaluation—`collect()` ကို ခေါ်မှသာ actual computation စတင်ပါတယ်—ဒါကြောင့် `iter.filter(...).map(...).collect()` chain ရေးရင် intermediate collection တွေ (filter result ကို ခွဲသိမ်းစရာ) ဆောက်စရာ မလိုတော့ပါ။ ဒီ iterator chain ကတော့ Java Stream API/JavaScript array method chain နှင့် ရုပ်ပိုင်းဆိုင်ရာ ဆင်တူပေမယ့် Rust မှာ monomorphization ကြောင့် (Lesson 13) hand-written `for` loop နှင့် performance အတိအကျ တူညီတဲ့ zero-cost abstraction ဖြစ်ပါတယ်—readability ကို readable style နဲ့ ရေးလို့ရပေမယ့် runtime cost ဘာမှ ထပ်ပေးစရာ မလိုပါဘူး—Rust community က ဒီ characteristic ကို "you don't pay for what you don't use" လို့ ခေါ်ကြပါတယ်။

လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်

Content analyzer ရဲ့ "minimum word count ကျော်တဲ့ lesson များကိုသာ ရှာ" logic ကို closure ဖြင့် `lessons.iter().filter(|l| l.word_count > min_words).collect()` လို ရေးမယ်—closure က `min_words` ကို enclosing scope ကနေ borrow လုပ်ကာ ခေါ်ပါတယ်။ Lesson title အားလုံးကို uppercase ပြောင်းချင်ရင် `lessons.iter().map(|l| l.title.to_uppercase()).collect::<Vec<String>>()` ဖြင့် chain ရေးမယ်—`for` loop ထက် readable ဖြစ်ပေမယ့် monomorphization ကြောင့် performance ဘာမှ ကျစရာ မလိုပါ။ Word count total ကို ရှာချင်ရင် `lessons.iter().map(|l| l.word_count).sum::<u32>()` ဖြင့် readable one-liner ရေးမယ်—intermediate `Vec` ကို build ချစရာ မလိုဘဲ lazy evaluation ကြောင့် `sum()` ခေါ်တဲ့အချိန်မှာပဲ traverse တစ်ကြိမ်တည်း ဖြစ်ပါတယ်။

အတူတူ စမ်းရေးကြည့်မယ်

rust
struct Lesson { title: String, word_count: u32 }

fn main() {
    let lessons = vec![
        Lesson { title: String::from("Ownership"), word_count: 620 },
        Lesson { title: String::from("Closures"), word_count: 340 },
        Lesson { title: String::from("Traits"), word_count: 700 },
    ];

    let min_words = 500;
    let long_titles: Vec<String> = lessons
        .iter()
        .filter(|l| l.word_count > min_words)
        .map(|l| l.title.to_uppercase())
        .collect();

    println!("{long_titles:?}");

    let total: u32 = lessons.iter().map(|l| l.word_count).sum();
    println!("total words: {total}");
}
You should see
`["OWNERSHIP", "TRAITS"]` နှင့် "total words: 1660" ကို print ထုတ်နိုင်မည်။

၅ မိနစ် စမ်းကြည့်

Integer `Vec<u32>` တစ်ခု ဖန်တီးပါ—`filter` ဖြင့် even number များသာ ရွေးပြီး `map` ဖြင့် နှစ်ဆတိုးကာ `collect()` ဖြင့် `Vec<u32>` အသစ်တစ်ခု ဖန်တီးပါ—closure တစ်ခုစီထဲမှာ variable တစ်ခု (threshold) ကို capture ထည့်သုံးကြည့်ပါ။

သတိလေးတစ်ချက်

Closure ကို `move` keyword ဖြင့် unnecessary သုံးပြီး outer scope ရဲ့ variable ကို ownership take သွားစေခြင်း—ဒီ variable ကို closure ပြီးနောက် outer scope ထဲက ဆက်သုံးမရတော့ဘဲ compile error ရနိုင်ပါတယ်—borrow (default) လုံလောက်ရင် `move` မလိုအပ်ပါ။

Iterator chain ကို `collect()` မခေါ်ဘဲ (lazy ဖြစ်လို့) actual computation ပြီးသွားပြီလို့ ထင်ခြင်း—`iter.filter(...)` တစ်ခုတည်းကို statement အဖြစ်ရေးရုံနှင့် ဘာမှ execute မဖြစ်သေးပါ—compiler က "unused iterator" warning ပေးလေ့ရှိပါတယ်။

The Rust Programming Language — Processing a Series of Items with IteratorsRust

ဒီနေရာမှာ လူအများမှားတတ်တယ်

  • Closure ကို `move` keyword ဖြင့် unnecessary သုံးပြီး outer scope ရဲ့ variable ကို ownership take သွားစေခြင်း—ဒီ variable ကို closure ပြီးနောက် outer scope ထဲက ဆက်သုံးမရတော့ဘဲ compile error ရနိုင်ပါတယ်—borrow (default) လုံလောက်ရင် `move` မလိုအပ်ပါ။
  • Iterator chain ကို `collect()` မခေါ်ဘဲ (lazy ဖြစ်လို့) actual computation ပြီးသွားပြီလို့ ထင်ခြင်း—`iter.filter(...)` တစ်ခုတည်းကို statement အဖြစ်ရေးရုံနှင့် ဘာမှ execute မဖြစ်သေးပါ—compiler က "unused iterator" warning ပေးလေ့ရှိပါတယ်။
  • နမူနာ code ကို production system ပေါ် တိုက်ရိုက်မစမ်းဘဲ local/test environment တွင် အရင်အတည်ပြုပါ။

လေ့ကျင့်ခန်း

Integer `Vec<u32>` တစ်ခု ဖန်တီးပါ—`filter` ဖြင့် even number များသာ ရွေးပြီး `map` ဖြင့် နှစ်ဆတိုးကာ `collect()` ဖြင့် `Vec<u32>` အသစ်တစ်ခု ဖန်တီးပါ—closure တစ်ခုစီထဲမှာ variable တစ်ခု (threshold) ကို capture ထည့်သုံးကြည့်ပါ။

You'll know it worked when: `["OWNERSHIP", "TRAITS"]` နှင့် "total words: 1660" ကို print ထုတ်နိုင်မည်။

Closures နှင့် Iterators | Thuta Learning