পাঠ ১০ · ৫৮-এর মধ্যে · মডিউল ২
Home / Courses / Concepts of Programming Languages & Compiler Design / মাল্টি-প্যারাডাইম

মাল্টি-প্যারাডাইম ল্যাঙ্গুয়েজ ও প্যারাডাইম বেছে নেওয়া

Multi-paradigm languages & choosing a paradigm
৭ মিনিট পড়া শুরু · Beginner Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • মাল্টি-প্যারাডাইম ভাষা কী এবং কেন বেশিরভাগ বাস্তব ভাষা এই পথ বেছে নিয়েছে
  • Python ও JavaScript-এ একসাথে একাধিক প্যারাডাইমের বাস্তব উদাহরণ
  • কোন সমস্যায় কোন প্যারাডাইম স্বাভাবিকভাবে ফিট করে তার একটি ব্যবহারিক সিদ্ধান্ত-কাঠামো (M2-এর সংশ্লেষণ)
  • Python-এ একই সমস্যা ইম্পারেটিভ, ফাংশনাল ও OOP — তিন শৈলীতে সমাধান করে সরাসরি তুলনা

১ · বেশিরভাগ বাস্তব ভাষা মাল্টি-প্যারাডাইম

L06-L09-এ আমরা চারটি প্যারাডাইম আলাদাভাবে দেখেছি — ইম্পারেটিভ, OOP, ফাংশনাল ও লজিক/ডিক্লারেটিভ। কিন্তু বাস্তবে বেশিরভাগ জনপ্রিয়, আধুনিক ভাষা মাল্টি-প্যারাডাইমMulti-Paradigm Languageএকটি ভাষা যা একাধিক প্রোগ্রামিং প্যারাডাইম মুক্তভাবে মিশ্রিত করে সমর্থন করে, একটিমাত্র প্যারাডাইমে সীমাবদ্ধ না থেকে। — একটিমাত্র প্যারাডাইমে সীমাবদ্ধ না থেকে একাধিক প্যারাডাইমের উপাদান মুক্তভাবে মেশায়। Python একইসাথে ইম্পারেটিভ (লুপ, মিউটেবল ভ্যারিয়েবল), OOP (ক্লাস, ইনহেরিটেন্স), এবং ফাংশনাল (lambda, প্রথম-শ্রেণির ফাংশন, map/filter) শৈলী — সবকিছু একটি ভাষার মধ্যেই সমর্থন করে। JavaScript একইভাবে ইম্পারেটিভ, OOP (প্রোটোটাইপ-ভিত্তিক, পাশাপাশি class সিনট্যাক্সও) এবং ফাংশনাল আইডিয়ম মেশায়।

২ · কেন মাল্টি-প্যারাডাইম ডিজাইন এত সাধারণ

এর পেছনে একটি সত্যিকারের, গুরুত্বপূর্ণ কারণ আছে: ভিন্ন ভিন্ন সমস্যা স্বাভাবিকভাবেই ভিন্ন ভিন্ন প্যারাডাইমে ভালো ফিট করে। একটি ডেটা-ট্রান্সফরমেশন পাইপলাইন প্রায়ই ফাংশনাল map/filter শৈলীতে বেশি স্পষ্ট পড়া যায়, আবার একটি স্টেটফুল সিমুলেশন (যেমন একটি গেম) প্রায়ই মিউটেবল অবজেক্টসহ ইম্পারেটিভ/OOP শৈলীতে স্বাভাবিকভাবে ফিট করে। একটি মাল্টি-প্যারাডাইম ভাষা প্রোগ্রামারকে বর্তমান সমস্যার জন্য সবচেয়ে উপযুক্ত শৈলী বেছে নেওয়ার স্বাধীনতা দেয়, বরং সবকিছুকে একটি নির্দিষ্ট ছাঁচে জোর করে ঢোকানোর বদলে।

৩ · প্যারাডাইম বেছে নেওয়ার সিদ্ধান্ত-কাঠামো

ইম্পারেটিভ/প্রসিডিউরাল
হার্ডওয়্যারের কাছাকাছি, সরাসরি ধাপে-ধাপে অ্যালগরিদমের জন্য — L06 দেখুন।
OOP
স্টেট+বিহেভিয়ার একসাথে থাকা বাস্তব-জগত সত্তা মডেলিং এবং পলিমরফিজম/এক্সটেনসিবিলিটি দরকার হলে — L07 দেখুন।
ফাংশনাল
নির্ভুলতা/টেস্টেবিলিটি/প্যারালালিজম-সেফটি সবচেয়ে গুরুত্বপূর্ণ হলে, অথবা সমস্যা স্বাভাবিকভাবেই ডেটা-ট্রান্সফরমেশন হিসেবে প্রকাশযোগ্য হলে — L08 দেখুন।
লজিক/ডিক্লারেটিভ
সমস্যা স্বাভাবিকভাবেই কনস্ট্রেইন্ট/সম্পর্ক হিসেবে প্রকাশযোগ্য হলে, স্পষ্ট অ্যালগরিদম হিসেবে নয় (যেমন ডেটাবেস কোয়েরি) — L09 দেখুন।

৪ · কোড: একই সমস্যা, তিনটি প্যারাডাইম

নিচের কোডে একটি সাধারণ সমস্যা — একটি সংখ্যার তালিকা থেকে শুধু জোড় সংখ্যা রেখে প্রতিটিকে দ্বিগুণ করা — তিনটি ভিন্ন প্যারাডাইম শৈলীতে সমাধান করা হয়েছে: ইম্পারেটিভ (এক্সপ্লিসিট লুপ + মিউটেবল রেজাল্ট লিস্ট), ফাংশনাল (চেইনড filter/map, কোনো মিউটেশন ছাড়াই), এবং OOP (একটি ছোট ক্লাস যা তালিকা মুড়িয়ে রাখে এবং মেথড চেইনিং সমর্থন করে)।

ইনপুট: [1, 2, 3, ..., 10] ইম্পারেটিভ: লুপ + append() ফাংশনাল: filter + map (lambda) OOP: NumberList মেথড চেইন ফলাফল: [4,8,12,16,20] — তিনটিতেই অভিন্ন
একই ইনপুট, একই কাঙ্ক্ষিত ফলাফল — কিন্তু তিনটি সম্পূর্ণ ভিন্ন কোড-শৈলী দিয়ে পৌঁছানো যায়, প্রোগ্রামারের পছন্দ ও সমস্যার প্রকৃতি অনুযায়ী।
Python
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# ১. ইম্পারেটিভ স্টাইল -- এক্সপ্লিসিট লুপ + মিউটেবল result লিস্ট
def imperative_version(nums):
    result = []
    for n in nums:
        if n % 2 == 0:
            result.append(n * 2)
    return result

# ২. ফাংশনাল স্টাইল -- চেইনড filter/map, কোনো মিউটেশন নেই
def functional_version(nums):
    return list(map(lambda n: n * 2, filter(lambda n: n % 2 == 0, nums)))

# ৩. OOP স্টাইল -- একটি ক্লাস যা তালিকা মুড়িয়ে রাখে, মেথড চেইনিং সমর্থন করে
class NumberList:
    def __init__(self, nums):
        self.nums = nums

    def filter_even(self):
        return NumberList([n for n in self.nums if n % 2 == 0])

    def double_all(self):
        return NumberList([n * 2 for n in self.nums])

oop_result = NumberList(numbers).filter_even().double_all().nums

imp = imperative_version(numbers)
fun = functional_version(numbers)

print("ইম্পারেটিভ:", imp)
print("ফাংশনাল:  ", fun)
print("OOP:       ", oop_result)
print("তিনটিই অভিন্ন:", imp == fun == oop_result)

    
হাতে-যাচাই: numbers-এর জোড় সংখ্যাগুলো হলো 2, 4, 6, 8, 10 — প্রতিটি দ্বিগুণ করলে হয় 4, 8, 12, 16, 20। তিনটি ফাংশনই এই একই তালিকা রিটার্ন করে, তাই imp == fun == oop_result মূল্যায়িত হবে True। লক্ষ্য করুন OOP সংস্করণে filter_even() ও double_all() প্রতিটি একটি নতুন NumberList অবজেক্ট রিটার্ন করছে (মূলটি মিউটেট করছে না) — এখানে সামান্য ফাংশনাল প্রভাবও মিশে আছে, যা মাল্টি-প্যারাডাইম চিন্তার একটি বাস্তব উদাহরণ।
মূল কথা · Key takeaway

M2 মডিউল জুড়ে আমরা দেখলাম প্রোগ্রামিং প্যারাডাইম আসলে "সঠিক বনাম ভুল" পছন্দ নয় — বরং একই সমস্যার একাধিক বৈধ সমাধান-দৃষ্টিভঙ্গি। একটি ভাষা যত বেশি প্যারাডাইম সমর্থন করে, প্রোগ্রামারের হাতে তত বেশি সরঞ্জাম থাকে — কিন্তু সেই স্বাধীনতা ব্যবহার করতে হলে প্রতিটি প্যারাডাইমের শক্তি ও দুর্বলতা বোঝা জরুরি, যা ঠিক এই মডিউলে (L06-L09) আমরা শিখেছি। M3 থেকে আমরা এখন ভাষার সিনট্যাক্স কীভাবে ফরমালি সংজ্ঞায়িত হয় সেদিকে যাব।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ Python-কে "মাল্টি-প্যারাডাইম" বলা হয় কেন — এটি কি ইম্পারেটিভ, OOP নাকি ফাংশনাল ভাষা?

তিনটিই একসাথে, কোনো একক উত্তর নেই — এবং সেটাই মূল বিষয়। Python-এ আপনি বিশুদ্ধ ইম্পারেটিভ লুপ লিখতে পারেন, আবার ক্লাস ও ইনহেরিটেন্স দিয়ে OOP কোড লিখতে পারেন, আবার lambda ও map/filter দিয়ে ফাংশনাল-ঘেঁষা কোডও লিখতে পারেন — এবং একই প্রোগ্রামে তিনটিই মিশিয়ে ব্যবহার করাও সম্পূর্ণ স্বাভাবিক (উপরের কোড সেলেই যেমন তিনটি শৈলী একসাথে দেখানো হয়েছে)। "মাল্টি-প্যারাডাইম" মানে ভাষাটি কোনো একটি প্যারাডাইমে প্রোগ্রামারকে আটকে রাখে না।

প্র ০২ যদি তিনটি প্যারাডাইম শৈলীই সবসময় একই ফলাফল দেয়, তাহলে কোনটি ব্যবহার করব তা কি গুরুত্বপূর্ণ?

হ্যাঁ, সত্যিই গুরুত্বপূর্ণ — যদিও এই ছোট উদাহরণে ফলাফল অভিন্ন, বাস্তব সিদ্ধান্তটি ফলাফল নিয়ে নয়, বরং পঠনযোগ্যতা, রক্ষণাবেক্ষণযোগ্যতা ও প্রসঙ্গ নিয়ে। একটি বড় ডেটা-প্রসেসিং পাইপলাইনে চেইনড filter/map প্রায়ই ইম্পারেটিভ লুপের চেয়ে বেশি সংক্ষিপ্ত ও স্পষ্ট পড়া যায়। কিন্তু জটিল, একাধিক শর্তসহ লজিকের ক্ষেত্রে একটি সাধারণ ইম্পারেটিভ লুপ প্রায়ই বেশি সহজবোধ্য হয়। L10-এর সিদ্ধান্ত-কাঠামো (চিপ-গ্রিড) ঠিক এই বাছাইয়ের জন্যই — সঠিক উত্তর প্রসঙ্গের ওপর নির্ভর করে।

প্র ০৩ OOP সংস্করণে NumberList(numbers).filter_even().double_all().nums — এই "মেথড চেইনিং" কীভাবে সম্ভব হচ্ছে?

এটি সম্ভব হচ্ছে কারণ filter_even() ও double_all() প্রতিটি একটি নতুন NumberList অবজেক্ট রিটার্ন করে (নিজের ভেতরেই মিউটেট করে না বা None রিটার্ন করে না)। যেহেতু প্রতিটি মেথডের রিটার্ন ভ্যালুও একটি NumberList, তার ওপর সাথে সাথে পরের মেথড কল করা যায় — a.filter_even() একটি NumberList দেয়, তার ওপর .double_all() কল করা যায়, যেটিও আরেকটি NumberList দেয়, শেষে .nums দিয়ে ভেতরের প্লেইন লিস্টটি বের করা হয়। এই প্যাটার্নে ফাংশনাল স্টাইলের "মূল ডেটা মিউটেট না করে নতুন মান রিটার্ন করা" নীতিটাই OOP মেথডের মধ্যে প্রয়োগ হয়েছে।

অনুশীলন

  1. পরীক্ষা করুন: উপরের কোডে numbers-এর মান [1, 2, 3, 4, 5] করে Run চাপুন — তিনটি সংস্করণেই কী ফলাফল আসবে?

    [1,2,3,4,5]-এর জোড় সংখ্যা শুধু 2 ও 4 — দ্বিগুণ করলে হয় 4 ও 8। তাই তিনটি সংস্করণই রিটার্ন করবে [4, 8], এবং imp == fun == oop_result এখনো True হবে — যেকোনো ইনপুট তালিকার জন্যই তিনটি বাস্তবায়ন একই লজিক অনুসরণ করে বলে ফলাফল সবসময় মিলবে।

  2. চিন্তা করুন: এই নির্দিষ্ট সমস্যাটির (জোড় ফিল্টার + দ্বিগুণ) জন্য L10-এর সিদ্ধান্ত-কাঠামো অনুযায়ী কোন প্যারাডাইম সবচেয়ে "স্বাভাবিক" ফিট মনে হয়, এবং কেন?

    ফাংশনাল স্টাইল — কারণ সমস্যাটি নিজেই একটি ডেটা-ট্রান্সফরমেশন পাইপলাইন ("এই তালিকা থেকে এই শর্তে ফিল্টার করো, তারপর এই রূপান্তর প্রয়োগ করো"), যা ঠিক filter/map-এর জন্য তৈরি প্যাটার্ন। তবে এটি একটি সাধারণীকরণ, নিয়ম নয় — একটি ছোট, সহজ কেসে ইম্পারেটিভ লুপও সমানভাবে পঠনযোগ্য, এবং যদি ফিল্টার/দ্বিগুণ করার লজিক জটিল স্টেটের ওপর নির্ভর করত, ইম্পারেটিভ বা OOP শৈলী হয়তো বেশি মানানসই হতো।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

  • কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৮টি পাঠ M2 প্রোগ্রামিং প্যারাডাইম মডিউল শেষ হলো — এরপর M3-এ ফরমাল গ্রামার ও সিনট্যাক্স শুরু হবে।
  • আগের পাঠ L09 লজিক ও ডিক্লারেটিভ প্রোগ্রামিং প্যারাডাইম — চতুর্থ প্যারাডাইম, যা এই পাঠের সিদ্ধান্ত-কাঠামোতে একত্রিত হয়েছে।
  • পরের পাঠ L11 ফরমাল ল্যাঙ্গুয়েজ ও গ্রামার পরিচিতি — M3 মডিউলের প্রথম পাঠ, যেখানে আমরা প্রোগ্রামিং ভাষার সিনট্যাক্স ফরমালি সংজ্ঞায়িত করা শুরু করব।
আগের পাঠ
লজিক ও ডিক্লারেটিভ প্রোগ্রামিং প্যারাডাইম