কিভাবে আমরা একটা স্ট্রিংকে ইটারেট করতে পারি ?
const name = "rashedule";
const nameIterator = name[Symbol.iterator]();
console.log(nameIterator.next());
console.log(nameIterator.next());
console.log(nameIterator.next());
console.log(nameIterator.next());
console.log(nameIterator.next());
console.log(nameIterator.next());
console.log(nameIterator.next());
console.log(nameIterator.next());
console.log(nameIterator.next());
console.log(nameIterator.next());
console.log(nameIterator.next());
console.log(nameIterator.next());
// এই কোড এঁর অউটপুট আসবে এরকম
{value: 'r', done: false }
{ value: 'a', done: false }
{ value: 's', done: false }
{ value: 'h', done: false }
{ value: 'e', done: false }
{ value: 'd', done: false }
{ value: 'u', done: false }
{ value: 'l', done: false }
{ value: 'e', done: false }
{ value: undefined, done: true }
{ value: undefined, done: true }
{ value: undefined, done: true }
এই ইটারেটর দিয়ে আমাদের কি কাজে আসবে ? আমরা চাইলেই একটা স্ট্রিং কে সাধারণভাবে ইটারেট করতে পারি না । হ্যাঁ করতে পারব তবে আগে আমাদের একটা স্ট্রিংকে স্প্লিট করে array তে কনভার্ট করে নিয়ে লুপ চালায়ে কাজ টা করে ফেলতেই পারি !
তবে আমাদের হাতে যখন ইটারেটর এঁর সুবিধা আছে তখন আমাদের এত কষ্ট করার দরকার কি । ইটারেটর এঁর মাধ্যমে আমরা একটা স্ট্রিং এঁর উপর খুব সহজেই লুপ চালাতে পারি । কিভাবে চলুন সেঁতাই দেখে নেই ।
const name = "rashedule";
const nameIterator = name[Symbol.iterator](); // এভাবে ইটারেটর বানাতে হয়
for (let v of name) {
console.log(v);
}
// আউটপুট
r
a
s
h
e
d
u
l
e
আমরা ইটারেটর এঁর সাহায্য ছাড়া এত সহজে কিন্তু একটা স্ট্রিং এঁর উপর লুপ চালিয়ে কাজ করতে পারলাম না । চলুন আমরা এইবাত পরের উদাহরণ দেখে নেই
ধরুন আমাদের একটা range নামক একটা অবজেক্ট আছে যেখানে বলা থাকবে আমাদের কোথা থেকে লুপ স্টার্ট করতে হবে কোথায় স্টপ করতে হবে এবং কত করে বাড়াতে হবে । এই অবজেক্টের উপর ভিত্তি করে আমাদের লুপ চালতে হবে । তো আমারা শুরুর দিকে এইভাবে কোডটা লেখে দেখতেই পারি । এবং আমাদের একটা বড়সড় একটা এঁরর দিবে
const range = {
start: 10,
stop: 100,
step: 5,
};
for (let v of range) {
console.log(v);
}
// TypeError: range is not iterable
এই সমস্যার সমাধান কিভাবে করতে পারি আমরা ? ইটারেটরের কঞ্চেপ্ট ব্যাবহার করে ।
জাই হোক এখন আমাদের কাজটাকে একটু সহজ করা যাক ।সেটা আমরা করতে পারি generator function এঁর মাধ্যমে । আগে generator function এঁর কিছু বাসিক জেনে নেই । generator function suspended নামক একটা অবজেক্ট রিটার্ন করে ।
gnFn.next() // কল করলে আমাদের একটা ভেলু আমার done স্ট্যাটাস দেখাবে ।
আমরা যে আগের উদাহরণে দেখলাম ঠিক সেই সেম কাজ আমারা এই generator function এঁর মাধ্যমে করতে পারি । generator function আমাদের কোডকে আরও রিডেবল করে দিয়েছে । এবং অনেক ছোট কোড লেখেই আমরা আমাদের ইটারেটর এঁর খাঁটি স্বাদ নিতে পারি ।
function* myGenerator() {
yield 1;
yield 2;
yield 3;
}
let iterator = myGenerator();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
// আউটপুট
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: undefined, done: true }
{ value: undefined, done: true }
আমরা generator function এঁর একটা বড় ব্যাবহার করতে ID generate করার কাজে । এটা আলাদা আলাদা করে ট্রাক রাখবে এবং সঠিক id (মানে কার পর কত id আসবে ) রিটার্ন করবে ।
function* generateId() {
let index = 1;
while (true) {
yield index++;
}
}
const generateUserId = generateId();
const generateProdId = generateId();
// user id
console.log("user", generateUserId.next());
console.log("user", generateUserId.next());
console.log("user", generateUserId.next());
// product id
console.log("prod", generateProdId.next());
console.log("prod", generateProdId.next());
console.log("prod", generateProdId.next());
// output
user { value: 1, done: false }
user { value: 2, done: false }
user { value: 3, done: false }
prod { value: 1, done: false }
prod { value: 2, done: false }
prod { value: 3, done: false }
// এখানে দেখুন প্রত্যেক টা ভেরিয়েবলের জন্য আলাদা আলাদা ID তৈরি করে দিয়েছে ।