Iterators ও Generators
Iterable, iterator, Symbol.iterator, for...of, generator function, yield — ধাপে ধাপে ডেটা চলার বাংলা গাইড।
for...of-এর মতো যেভাবে array-কে ঘোরা যায় — সেটাই যেকোনো নিজস্ব type-এ আনা যায় iterator দিয়ে। আর generator দিয়ে মান তৈরি হয় ধাপে ধাপে, paused অবস্থায় — দুটোই advanced কিন্তু দৈনন্দিন জাদু।
Iterable — যা ঘোরা যায়
const iterable = ["আম", "কলা"];
for (const fruit of iterable) {
console.log(fruit);
}
// আম
// কলা
// strings-ও iterable
for (const ch of "দেশ") {
console.log(ch); // দ, ে, শ (অক্ষর ভাঙা নয় — code point)Array, string, Map, Set — iterable। for...of, spread (...), Promise.all — এরা iterable-কে চালায়।
Iterator কি
iterator হলো object যার next() method আছে — প্রতি call-এ { value, done } দেয়। Symbol.iterator তৈরি করে iterable।
// নিজস্ব iterable
const countdown = {
from: 3,
[Symbol.iterator]() {
let current = this.from;
return {
next: () => {
if (current >= 0) {
return { value: current--, done: false };
}
return { done: true };
},
};
},
};
for (const n of countdown) {
console.log(n); // 3 2 1 0
}
console.log([...countdown]); // [3, 2, 1, 0]iterator-এর next()-এ প্রথম object-এ value, শেষে done: true — যতক্ষণ done না, লুপ ততক্ষণ চলে।
Generator — generator function
function* countTo(max) {
for (let i = 1; i <= max; i++) {
yield i; // pause — এখানে
}
}
const gen = countTo(3);
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }function* + yield — generator। প্রতিবার .next()-এ yield-এ গিয়ে থামে, মান দিচ্ছে। generator নিজেই iterator।
for...of দিয়ে generator
function* fib() {
let a = 0, b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
// সীমাহীন ধারা — তবে for...of দরকার মোতাবেক ঘোরাতে
let count = 0;
for (const n of fib()) {
if (count === 10) break;
console.log(n); // 0 1 1 2 3 5 8 ...
count++;
}generator-এর সুবিধা — lazy: পুরো ধারা আগে থেকে বানানো নয়, যতটুকু দরকার ততটুকুই। সীমাহীন sequence-এর জন্য সবচেয়ে দরকারি।
yield-এ যোগাযোগ
function* ask() {
const name = yield "তোমার নাম?";
return "নমস্কার, " + name;
}
const g = ask();
console.log(g.next()); // { value: "তোমার নাম?" }
console.log(g.next("রহিম")); // { value: "নমস্কার, রহিম", done: true }
// .next(value) — yield-এ ফেরত পাঠানোyield* — delegation
function* inner() {
yield 1;
yield 2;
}
function* outer() {
yield "শুরু";
yield* inner(); // পুরো inner-এর yield চালায়
yield "শেষ";
}
console.log([...outer()]); // ["শুরু", 1, 2, "শেষ"]অলস ক্রম — ID generator
function* idGenerator(prefix = "id_") {
let id = 0;
while (true) {
yield prefix + ++id;
}
}
const ids = idGenerator();
console.log(ids.next().value); // id_1
console.log(ids.next().value); // id_2ID-এর মতো ক্রম তৈরিতে generator দারুণ — মেমরি না ভরানো, চাইলে পরেরটা। React keys/DB IDs-এর কথা ভাবুন।
| ধারণা | সারাংশ |
|---|---|
| Iterable | for...of-চালু object |
| Iterator | next() → {value, done} |
Symbol.iterator | iterable-এর factory |
| Generator | function* + yield |
yield* | অন্য generator-এর delegation |
| Lazy | যতটুকু চাও, ততটুকু। |
generator-এর iterator একদিকের — একবার শেষ হলে নতুন instance বানিয়ে আবার শুরু করতে হয়।
"Generator কখন ব্যবহার করবেন?" — large/infinite sequence, lazy evaluation, custom iteration — কথাগুলো বলে উদাহরণ দিলে পরিপূর্ণ উত্তর।
একটি function* দিয়ে weekly routine (৭টি step) লিখুন — for...of দিয়ে ঘোরান।