যখন আপনি আপনার সংগ্রহগুলোকে এনুমেরেটর হিসেবে বিবেচনা করেন, তবে আপনি #map এবং #reduce-এর মতো সব প্রিয় ফাংশনগুলো ব্যবহার করতে পারেন যেকোনো অতিরিক্ত কোড লিখতে ছাড়া। এটি খুবই অসাধারণ।
পুরনো দিনগুলোর এনুমেরেটর
পুরনো দিনগুলিতে, এনুমেরেটর ডিফাইন করা কিছুটা কষ্টসाध्य ছিল। আপনাকে একটি নতুন ক্লাস তৈরি করতে হতো, Enumerable মডিউল ইনক্লুড করতে হতো, এবং একটি #each ফাংশন ডিফাইন করতে হতো।
তবে রুবি ১.৯ এর পর থেকে, আমাদের কাছে এনুমেরেটর অন-দ-ফ্লাই ডিফাইন করার একটি অনেক হালকা উপায় আছে। চলুন এক নজর দেই।
Enumerator ক্লাস পরিচয়
Enumerator ক্লাস আপনাকে একটি এককালীন এনুমেরেটর ডিফাইন করতে দেয়, ব্লক সিনট্যাক্স ব্যবহার করে। নিচের উদাহরণে, আমরা একটি এনুমেরেটর তৈরি করছি যা র্যান্ডম সংখ্যার একটি অসীম সিরিজ রিটার্ন করে।
e = Enumerator.new do |y|
loop do
y << rand(10) # << অপারেটর একটি মান "yield" করে
end
end
# এনুমেরেটরকে ১০টি মান "yield" করে বন্ধ করুন
puts e.first(10).inspect # => [6, 6, 7, 2, 2, 9, 6, 8, 2, 1]
আপনি লক্ষ্য করতে পারেন যে আমরা শিফট অপারেটর << ব্যবহার করছি একটি অস্বাভাবিক উপায়ে। এটি y.yield মেথডের একটি শর্টকাট। আপনি এনুমেরেটরের প্রতিটি আইটেমের জন্য এটি কল করবেন। যদি এটি কিছুটা জাদুई লাগে, তাহলে চিন্তা করবেন না। এটি সত্যিই।
সংগ্রহের আকার
একটি সংগ্রহের আকার নির্ধারণ করা রুবির লেজি এনুমেরেটরগুলোর জন্য একটি সমস্যা তৈরি করে। একটি সংগ্রহের আইটেম গণনা করার জন্য, আপনাকে পুরো সংগ্রহ লোড করতে হয় - যা লেজি এনুমেরেটর ব্যবহারের মূল উদ্দেশ্যের বিপরীত।
এখানে একটি ওয়ার্কঅরাউন্ড আছে, প্রকারে। যদি আপনি Enumerator তৈরি করার সময় সংগ্রহের আকার জানেন, তবে আপনি তা প্রদান করতে পারেন।
# আপনি কনস্ট্রাক্টরে দৈর্ঘ্য আর্গুমেন্ট হিসেবে পাস করতে পারেন, যদি আপনার কাছে থাকে
e = Enumerator.new(10) do |y|
10.times { y << rand }
end
আমার রিয়েল-ওয়ার্ল্ড উদাহরণ
গতকাল আমি Honeybadger-এর নতুন ডকুমেন্টেশন সাইটে কাজ করছিলাম। এটি Jekyll দিয়ে তৈরি, এবং আমি <h2> এবং <h3> ট্যাগের ভিত্তিতে একটি টেবিল অফ কন্টেন্টস তৈরি করার জন্য একটি প্লাগইন লিখছিলাম।
<h2> ট্যাগ দ্বারা সংজ্ঞায়িত একটি সেকশনে কোন <h3> ট্যাগগুলো বেস করে তা বের করা কিছুটা অসুবিধাজনক। আপনাকে Nokogiri ব্যবহার করে HTML পার্স করতে হয়, এবং তারপর ফলাফল ডকুমেন্ট স্ক্যান করতে হয়। তাই আমি কোডের সেই অংশটি আলাদা করে একটি Enumerator বানালাম। এটা কেমন দেখায় তার উদাহরণ নিচে দেওয়া হলো।
def subheadings(el)
Enumerator.new do |y|
next_el = el.next_sibling
while next_el && next_el.name != "h2"
if next_el.name == "h3"
y << next_el
end
next_el = next_el.next_sibling
end
end
end