হাইয়ার অর্ডার ফাংশন (Higher Order Function)

শুরুতেই বিষয়টাকে একটু সহজ করার চেষ্টা করি। কারণ এই বিষয়টা সহজ হলেও বুঝতে গিয়ে অনেকেই গোলমাল পাকিয়ে ফেলে। ধরে নিন আপনি কোন ব্যাক্তিকে কখন হাইয়ার ক্লাসের লোক লোক বলবেন? যখন সে অনেক দায়িত্ব বা অনেক ডিপার্টমেন্ট সামলাচ্ছে। বিষয়টা আরো একটু ভাল করে বুঝার করার জন্য আমি ধরে নিতে পারি আপনার অফিসের CEO সাহেবকে। প্রশ্ন করুন নিজেকে কেন তিনি CEO ? দেখবেন তিনি হচ্ছেন এমন একজন ব্যাক্তি যে, অনেক লোকজনকে দিয়ে কাজ করাচ্ছেন এবং বিভিন্ন নিয়ম নিতি মেনে কোম্পানির সাফল্যে কাজ করে যাচ্ছেন। এক কথায় বলতে পারেন, অফিসে হাইয়ার লেভেল কাজ কর্ম গুলো তার দ্বারা বাস্তবায়িত হচ্ছে কোন না কোন ভাবে। হয় নিজের অফিসের লোকজন কে দিয়ে করিয়ে নিচ্ছেন না হয় বাইরের কাউকে দিয়ে। দিন শেষে তিনি প্রয়োজনীয় কাজ গুলো করিয়ে নিচ্ছেন।

সংজ্ঞাঃ- হাইয়ার অর্ডার ফাংশন এমন একটা ফাংশন যেখানে আমরা আরেকটা ফাংশনকে প্যারামিটার হিসেবে পাস করব। অথবা এর ভিতরে এক বা একাধিক ফাংশন লিখে আমাদের চাহিদা মতো কাজ করিয়ে নিব। টিক আমাদের অফিসের CEO সাহেবের মতো।

এখন আমরা এমন একটা প্রোগ্রাম লিখব যেখানে আমাদের কিছু অ্যারে উপাদান থাকবে এবং আমরা ঐ অ্যারে এর প্রত্যেকটা উপাদানকে 2 দ্বারা গুন করে আরেকটা নতুন অ্যারে বানাব। চলুন দেখে নেই।

multiply-array-el-by-2.js
let elements = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let new_array = [];
for ( let element of elements ) {
    new_array.push( element * 2 );
  }
  
console.log(new_array)

Output:

[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

এখন আসুন আমরা আসলে এই প্রোগ্রামটা নিয়ে একটু চিন্তা করি। কেন? কিভাবে? কি হচ্ছে ?

প্রথমে আমরা একটা elements নামে অ্যারে নিয়েছি টিক ১ নম্বার লাইনের মতো করে। এবং new_array নামে আরেকটা empty অ্যারে নিয়েছি টিক ২ নাম্বার লাইনের মতো করে। পরে for loop ব্যাবহার করে প্রতিটা element কে 2 দিয়ে গুন করার পর new_array অ্যারেতে পুশ করে দিয়েছি। টিক যেমন টা দেখতে পাচ্ছেন ৩ থেকে ৫ নাম্বার লাইনের কোড গুলো। এবং সবশেষে কনসোল করে প্রিন্ট করা হয়েছে টিক যেমনটা দেখতে পাচ্ছেন ৭ নাম্বার লাইনে।

এবার আসি আমরা এই যে কোড টা লিখলাম এতে আমাদের কাজ হচ্ছে কিন্তু কেউ যখন আমাদের বলবে ভাই 2 এর পরিবর্তে এবার 3 দিয়ে করে দেখান। অথবা আরেকজন বলল ভাই আমি গুন করব না আমি ভাগ করব। এমন আরো অনেক বিষয় বা সমস্যা তৈরি হতেই পারে একেক জন একেক ভাবে তাদের চিন্তার ভাব যুক্ত করতেই পারে কেমন হতো? যদি আমরা বিষয়টা কে একটু ডাইনামিক ভাবে করে দিতে পারি। যাতে করে যে যেমন লজিক লিখতে চাই সে শুধু ততটুকুই লিখবে। আসুন দেখে নেই।

function map( array, myDynamicFunction ) {
  let mapped = [];
  for ( let element of array ) {
    mapped.push(myDynamicFunction(element));
  }
  return mapped;
}

//multiply by 2
function multiply( element ){
  return element * 2;
}

//divide by 2
function divide( element ){
  return element / 2;
}

let elements = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

const results_of_multiplication = map(elements,multiply);
 
const results_of_division =  map(elements,divide);

আসুন কোডটা একটু বুঝে নেই কি হচ্ছে? প্রথমে আমি একটা ফাংশন লিখে নিয়েছি map নামে। যেমন টা দেখতে পাচ্ছেন ১-৭ নাম্বার লাইনের মত করে। যে ফাংশনটা প্যারামিটার হিসেবে দুইটা প্যারামিটার নেয়। প্রথমটা হচ্ছে array দ্বিতীয়টা হচ্ছে আমাদের দেওয়া ডাইনামিক ফাংশন যেইটাকে আমি আসলে myDynamicFunction নামে লিখেছি। এবং পরে map ফাংশন টা আমাদের myDynamicFunction কল করার পর যা রিটার্ন করছে সেইটা আমাদের mapped অ্যারে তে পুশ করে দিচ্ছে টিক লাইন নাম্বার এর মতো করে। এর পরে আমি আরও দুইটা ফাংশন লিখেছি multiply নামে লাইন নাম্বার ১০ - ১২ এবং divide নামে লাইন নাম্বার ১৪ - ১৭multiply ফাংশনটা একটা প্যারামিটার নিচ্ছে এবং দুই দিয়ে গুন করছে। আর divide ফাংশনটাও একটা প্যারামিটার নিচ্ছে এবং পরে সেইটা কে দুই দিয়ে ভাগ করছে। পরে আমরা ১৯ নাম্বার লাইনের মতো করে একটা অ্যারে নিয়েছি যার নাম দিয়েছি elements এবং সেখানে আমরা কিছু সংখ্যা রেখেছি। এর পরে ২১ নাম্বার লাইনের মতো করে আমি map ফাংশন টা কল করে নিয়েছি এবং সেইটাতে আমাদের elements অ্যারে এবং multiply ফাংশনটা পাস করে দিয়েছি এবং যে রেজাল্টটা পাচ্ছি সেইটা results_of_multiplication নামে একটা ভেরিয়েবলে রেখে দিচ্ছি। একই কাজ টা আমি লাইন নাম্বার ২৩ এ করেছি শুধু multiply এর পরিবর্তে divide লিখেছি এবং রেজাল্ট যেইটা পেয়েছি সেইটা results_of_division ভেরিয়েবলে রেখে দিয়েছি।

একবার ভালো করে দেখুন তো আগের কোডে আপনি শুধু মাত্র এক ধরনের কাজ করতে পারতেন। আর এখন আপনি আপনার ইচ্ছা মতো কাজ করতে পারছেন। বিষয়টা সত্যিই মজার তাই না! তাছাড়া আগের কোডের দিকে লক্ষ্য করলে দেখবেন আপনার প্রতিটা লাইন দেখার পর বলতে পারতেন এই কোডটা আসলে কি করবে? কিন্তু আমরা পরে যে কোড লিখেছি সেইটা ডাইনামিক অপারেশনের সাথে সাথে বোধগম্য কোডও দিচ্ছে। যেটা আসলেই অনেক ইফেক্টিভ অন্য প্রোগ্রামারদের জন্য যখন একসাথে কাজ করবেন।

এমন অনেক কাজেই আছে যেগুলো আপনি নিমিষেই এমন ফাংশন লিখে করে ফেলতে পারেন আর রি-ইউজেবল করতে পারেন।

কিছু প্রশ্নের উত্তর আপনার জানতে ইচ্ছা হবে এখন সেগুলো আমি উত্তর সহ নিচে বলে দিলাম

১। হাইয়ার অর্ডার ফাংশন কি সবসময় কিছু রিটার্ন করবে?

উত্তরঃ না! হাইয়ার অর্ডার ফাংশন আপনাকে রিটার্ন করবে কি করবে না সেইটা আপনার কাজের উপর নির্ভর করবে। কারণ সবসময় কিছু রিটার্ন চাইবেন এমন কাজ নাও করতে পারেন।

২। জাভাস্কিপ্টে কি Built-in হায়ার অর্ডার ফাংশন আছে?

উত্তরঃ হ্যাঁ। জাভাস্ক্রিপ্টে অনেক গুলো হায়ার অর্ডার ফাংশন আছে জেমনঃ map, filter, find, forEach ইত্যাদি

৩। বিল্ড ইন এবং কাস্টম হায়ার ওর্ডার ফাংশনের কি কোন limitation আছে?

উত্তরঃ হ্যাঁ ! আপনি যখন কোন Asynchronous টাস্ক করতে যাবেন আশা অনুরূপ রেজাল্ট নাও পেতে পারেন। তাছাড়া আপনি যে কাস্টম ফাংশনটা লিখেছেন অবস্যই একটা কমন প্যাটার্ন এ লিখতে হবে না হয় আশা অনুরূপ ফলাফল নাও পেতে পারেন।

৪। হায়ার অর্ডার ফাংশনের টাইম কমপ্লেক্সিটি কত?

উত্তরঃ বুদ্ধিমানের উত্তর হচ্ছে আপনি যেমন কোড লিখবেন টাইম কমপ্লেক্সিটি ও তেমন হবে। তবে প্রশ্নটা যদি এমন হয় যে জাভাস্ক্রিপ্টে built-in ফাংশন গুলোর কমপ্লেক্সিটি নিয়ে তাহলে উত্তর হচ্ছে O(n)।

Last updated