Iterators (ইটারেটরস)
ইটারেটর হচ্ছে একটি অবজেক্ট যা একটি কালেকশন (যেমন অ্যারে, ভেক্টর, ইত্যাদি) বা সিকোয়েন্সের উপাদান এক এক করে পর্যালোচনা করতে সাহায্য করে। রাস্টে, ইটারেটর হল এমন একটি ট্রেইট (trait) যা next() মেথডের মাধ্যমে পরবর্তী উপাদানটি রিটার্ন করে, যতক্ষণ না সব উপাদান পর্যালোচনা হয়ে যায়।
ইটারেটরের মূল কাজ:
- পর্যায়ক্রমে উপাদান অ্যাক্সেস করা: ইটারেটর আপনাকে একে একে সব উপাদান অ্যাক্সেস করতে সাহায্য করে।
- অবজেক্টের উপর লুপ চালানো: ইটারেটর আপনাকে একটি সিকোয়েন্সের উপর সহজে লুপ চালানোর সুযোগ দেয়।
সিনট্যাক্স:
let iterator = collection.iter();ইটারেটর এর উদাহরণ:
fn main() {
let nums = vec![1, 2, 3, 4, 5];
let mut iterator = nums.iter(); // ইটারেটর তৈরি
println!("{}", iterator.next().unwrap()); // 1
println!("{}", iterator.next().unwrap()); // 2
println!("{}", iterator.next().unwrap()); // 3
}এখানে:
nums.iter()হল একটি ইটারেটর যাnumsভেক্টরের উপাদানগুলো একে একে রিটার্ন করবে।next()মেথড দ্বারা পরবর্তী উপাদান রিটার্ন হয়, এবং যদি কোন উপাদান না থাকে, তাহলেNoneফেরত দেয়।
Lazy Evaluation (লেজি ইভালুয়েশন)
Lazy Evaluation একটি কৌশল যেখানে একটি ফলাফল তখনই গণনা করা হয়, যখন সেটি প্রয়োজন হয়। অর্থাৎ, কোনো ক্যালকুলেশন বা প্রক্রিয়া তখনই সম্পাদিত হয় যখন সেটির রেজাল্ট প্রয়োজন হয়, পূর্বে থেকে এটি গণনা করা হয় না।
রাস্টের ইটারেটরগুলি lazy evaluation পদ্ধতিতে কাজ করে। এর মানে হলো, ইটারেটরগুলি যতটুকু প্রয়োজন, ততটুকুই কাজ করে, এবং পুরো সিকোয়েন্সটি একসাথে প্রক্রিয়া করা হয় না, বরং এক এক করে শুধুমাত্র যে উপাদানটি প্রয়োজন সেটিই রিটার্ন করা হয়।
উদাহরণ:
fn main() {
let nums = vec![1, 2, 3, 4, 5];
let sum: i32 = nums.iter()
.map(|x| x * 2) // প্রতিটি উপাদানকে ২ দিয়ে গুণ করা
.filter(|x| x > &5) // ৫ এর চেয়ে বড় মানগুলো ফিল্টার করা
.sum(); // সব মান যোগ করা
println!("The sum is: {}", sum);
}এখানে:
.map(|x| x * 2)প্রতিটি উপাদানকে ২ দিয়ে গুণ করছে।.filter(|x| x > &5)ফিল্টার করছে, কেবলমাত্র ৫ এর চেয়ে বড় উপাদানগুলো রাখতে।.sum()সমস্ত মান যোগ করছে।
Lazy Evaluation:
- Lazy evaluation দ্বারা শুধুমাত্র প্রয়োজনীয় কাজই ঘটবে। উদাহরণস্বরূপ,
.map()এবং.filter()শুধু তখনই কার্যকর হবে যখন.sum()মেথড কল হবে। এখানে পুরো সিকোয়েন্স একসাথে প্রক্রিয়া করা হয় না, বরং এক এক করে উপাদানগুলো পর্যালোচনা করা হয়।
ইটারেটর ট্রেইট এবং লেইজি ইভালুয়েশন
রাস্টের ইটারেটরগুলি Lazy Evaluation কে ব্যবহার করে, অর্থাৎ যখন আপনি কোনো ইটারেটরের উপর অপারেশন করবেন, তখন তা তখনই কার্যকর হবে যখন আপনি ফলাফলটি ব্যবহার করবেন। কিছু সাধারণ ইটারেটর মেথড যেগুলি লেইজি ইভালুয়েশন অনুসরণ করে:
map(): প্রতিটি উপাদানকে একটি নির্দিষ্ট ফাংশনের মাধ্যমে পরিবর্তন করে।filter(): একটি শর্ত অনুযায়ী উপাদানগুলো ফিল্টার করে।take(): একটি নির্দিষ্ট সংখ্যক উপাদান নেয়।skip(): প্রথম কিছু উপাদান স্কিপ করে।
উদাহরণ:
fn main() {
let nums = vec![1, 2, 3, 4, 5];
// লেইজি ইভালুয়েশন: এখানে ইটারেটরগুলি পরে এক এক করে কাজ করবে
let result: Vec<i32> = nums.iter()
.filter(|&x| x % 2 == 0) // ২ দিয়ে ভাগযোগ্য উপাদান ফিল্টার
.map(|x| x * 2) // পরবর্তী সব মানকে গুণে ২ দিয়ে বাড়ানো
.collect(); // ফলাফলকে একটি ভেক্টরে সংগ্রহ করা
println!("{:?}", result); // [4, 8]
}এখানে:
- Lazy Evaluation চালানোর সময়,
.filter()এবং.map()একে একে উপাদানগুলোর উপর কাজ করবে। সম্পূর্ণ সিকোয়েন্সটি প্রক্রিয়া করা হয় না, বরং শুধুমাত্র ফলাফল প্রাপ্তির সময়ই অপারেশনগুলি কার্যকর হবে।
Lazy Evaluation এর সুবিধা
- দ্রুততা বৃদ্ধি: শুধুমাত্র যে উপাদানটি প্রয়োজন তা প্রক্রিয়া করা হয়, ফলে অপারেশন দ্রুত হয়।
- মেমোরি সাশ্রয়ী: লেইজি ইভালুয়েশন কম মেমোরি ব্যবহার করে, কারণ পুরো সিকোয়েন্স একবারে মেমোরিতে রাখা হয় না।
- কমপ্লেক্স প্রোগ্রামিং: লেইজি ইভালুয়েশন উচ্চ স্তরের অ্যাবস্ট্রাকশন ব্যবহারের মাধ্যমে কমপ্লেক্স সমস্যা সমাধান করা সহজ করে তোলে।
সারাংশ
Iterators এবং Lazy Evaluation রাস্টের দুটি শক্তিশালী বৈশিষ্ট্য। ইটারেটরগুলি একটি সিকোয়েন্সের উপাদান এক এক করে পর্যালোচনা করতে সাহায্য করে, এবং Lazy Evaluation নিশ্চিত করে যে কোডটি শুধুমাত্র প্রয়োজনীয় সময়েই কাজ করে, ফলে এটি মেমোরি এবং কার্যক্ষমতা সাশ্রয়ী হয়ে থাকে। এই দুটি বৈশিষ্ট্য একত্রে কোডকে আরও দক্ষ, দ্রুত এবং সহজে ব্যবহৃত করতে সহায়তা করে।
Read more