Ada-তে Generic Programming — Type দিয়ে contract লিখে zero-cost reuse

· হালনাগাদের তারিখ: · · Ada, Programming Language, Generics, Type System, Static Typing, Contract Model, Zero Cost Abstraction, GNAT, Alire, উচ্চ নির্ভরযোগ্যতা, কোড পুনর্ব্যবহার

1. ভূমিকা — «যা খুশি নেবে» নয়, «কী প্রতিশ্রুতি দিচ্ছে»

Statically typed ভাষায় পুনর্ব্যবহারযোগ্য কোড লিখতে গেলে একই সমস্যায় ধাক্কা লাগে। Integer-এর জন্য লেখা stack string-এও ব্যবহার করতে চান। Floating-point array-তেও একই পরিসংখ্যান চালাতে চান। Ascending sort-এর logic descending-এও লাগাতে চান। কিন্তু type অনুযায়ী একই কোড কপি করতে থাকলে সংশোধন ছুটে যায়। উল্টো void* বা cast দিয়ে যা খুশি নেওয়ার ডিজাইন করলে type safety ভেঙে পড়ে।

Ada-র উত্তর generic (generic units)

Ada-র generic সাধারণ text substitution নয়। Type, value, subprogram, এমনকি package নিজেকে formal parameter হিসেবে নেয়, আর instantiation-এর মুহূর্তে statically type-check হয়। অর্থাৎ runtime-এ «এই type-এ সত্যিই চলবে কি না» খোঁজে না; compile-time-এ «এই অংশ এই contract পূরণ করে কি না» স্থির করে।

পুনর্ব্যবহারের তিন পথCopy-paste, void-star বা Object বা cast, এবং Ada generic-এর মধ্যে পুনর্ব্যবহারের উপায় ও তার ফল দেখানো চিত্র।পুনর্ব্যবহার করতে চাওয়া logicকীভাবে পুনর্ব্যবহার করবেনCopy-pastevoid* / Object / castAda genericসংশোধন ছুটে যাওয়ার সম্ভাবনা বেশিRuntime error ও type ভাঙার সম্ভাবনা বেশিType-safeCompile-time checkRuntime-এ extra dispatch নেই

এই নিবন্ধে Ada-র generic programming নিচের ক্রমে সাজানো হয়েছে।

  • Generic subprogram
  • Generic package
  • Type parameter, value parameter, subprogram parameter
  • private, range <>, digits <> ইত্যাদি type category
  • Sort, stack, পরিসংখ্যান, Count_If, key-value store-এর বাস্তবায়ন উদাহরণ
  • Formal package parameter দিয়ে higher-order generic
  • Ada-র contract model ও বাস্তব ডিজাইনের ধারণা

1.1 কাদের জন্য, আর এখান থেকে কী নিয়ে যাবেন

এই নিবন্ধ এই পাঠকদের কথা মাথায় রেখে লেখা।

  • C++ template, C# বা Java generic, অথবা Rust generic — এগুলোর কোনো একটা ব্যবহার করেছেন
  • Ada-র syntax-এ গভীর নন, কিন্তু «type দিয়ে contract লেখা» ডিজাইনে আগ্রহ আছে
  • দীর্ঘ রক্ষণাবেক্ষণ, embedded, উচ্চ নির্ভরযোগ্যতার ক্ষেত্রে reuse-এর অংশ কীভাবে ডিজাইন করবেন ভাবছেন

Ada syntax হিসেবে package (specification .ads ও body .adb-এর আলাদা থাকা) এবং in / out / in out parameter mode জানলেই পড়া যায়। এই দুটোতে অনিশ্চয়তা থাকলে আগে «Ada ভাষার আকর্ষণ» পড়ে নিলে বোঝা তাড়াতাড়ি হয়।

নিয়ে যাওয়ার জিনিসটা Ada-র syntax নিজে নয়, পুনর্ব্যবহারযোগ্য অংশ কী চায় তা বাস্তবায়নের আগে type হিসেবে লিখে ফেলা — এই ডিজাইন অভ্যাস। C#-এর interface constraint বা C++20 concepts কতদূর লিখবেন ঠিক করার সময়ও একই ধারণা লাগে।

1.2 পড়ার গাইড — সব অধ্যায় পড়তেই হবে না

নিবন্ধে ২০টি অধ্যায় আছে। ধারাবাহিক না পড়েও উদ্দেশ্য অনুযায়ী এভাবে তুলে পড়া যায়।

উদ্দেশ্য যে অধ্যায়গুলো পড়বেন
শুধু ধারণা অল্প সময়ে ধরতে চান অধ্যায় ৪ (মৌলিক মডেল) → অধ্যায় ৬ (সবচেয়ে ছোট generic subprogram) → অধ্যায় ১৩ (contract model)
নিজে অংশ লিখতে চান অধ্যায় ৪ → অধ্যায় ৬ → অধ্যায় ৭ (generic package) → অধ্যায় ৮ (behavior inject) → অধ্যায় ৯ (type category)
শুধু ডিজাইন সিদ্ধান্তের নির্দেশিকা চান অধ্যায় ১৩ → অধ্যায় ১৪ (কী generic করবেন) → অধ্যায় ১৫ (যেখানে হোঁচট) → অধ্যায় ১৭ (চেকলিস্ট)
হাতে কলমে চালাতে চান অধ্যায় ৩-এ পরিবেশ বানিয়ে অধ্যায় ৬ ও ৭-এর সম্পূর্ণ নমুনা থেকে

সবচেয়ে ছোট পথ অধ্যায় ৪, ৬ ও ১৩ — এই তিনটি। এই তিনটিতে formal parameter, instantiation ও contract model — মূল জিনিসগুলো এসে যায়। অধ্যায় ৫ ও ৯ formal parameter-এর তালিকা, তাই দরকার হলে অভিধানের মতো খুলে দেখলেই চলে।

বিষয়টি এই ব্লগের ধারাবাহিক «Ada ভাষার আকর্ষণ», «SPARK দিয়ে formal verification পরিচিতি», «নিরাপদ concurrency», «Real-time সিস্টেম»-এর পরের কিস্তি। Ada-র «type দিয়ে ডিজাইন বলা» ধারণাকে generic-এর কোণ থেকে খোলা হয়েছে।

এই নিবন্ধের জ্ঞান মানচিত্র

Ada-এর জেনেরিক type · value · subprogram · package-কে formal প্যারামিটার হিসেবে নেয় এবং new দিয়ে ইনস্ট্যান্সিয়েশনের সময়েই স্ট্যাটিক টাইপ চেক হয়—এমন পুনর্ব্যবহারের ব্যবস্থা। জেনেরিক subprogram ও জেনেরিক প্যাকেজ এই ব্যবস্থার দুই স্তম্ভ; formal type প্যারামিটার private বা range<>, digits<> ইত্যাদি ক্যাটাগরি দিয়ে বডিতে যে অপারেশন ব্যবহার করা যাবে তার চুক্তি স্পষ্ট করে, formal subprogram প্যারামিটার দিয়ে তুলনা বা predicate-এর মতো আচরণ ঢুকিয়ে দেয়, আর formal package প্যারামিটার দিয়ে আগেই instantiate করা জেনেরিক প্যাকেজকে কম্পোনেন্ট হিসেবে গ্রহণ করে। এই চুক্তিকে কেবল formal প্যারামিটারের সীমার ভিতরে বডি একাই চেক করার contract model-এর ফলে, C++ টেমপ্লেট যে ঐতিহাসিকভাবে ইনস্ট্যান্সিয়েশন করে তবেই ত্রুটি জানা যায় সেই সমস্যা Ada-তে কাঠামোগতভাবে ঘটে না। GNAT ও Alire থাকলে এই ব্যবস্থা বিনামূল্যের পরিবেশে পরীক্ষা করা যায়।

Ada জেনেরিক প্রোগ্রামিংয়ের জ্ঞান মানচিত্রজেনেরিক subprogram ও জেনেরিক প্যাকেজ যেভাবে type · value · subprogram · package এই formal প্যারামিটারের চুক্তি (contract model)-এর উপর দাঁড়ায় এবং new দিয়ে ইনস্ট্যান্সিয়েশনে সেই চুক্তি যাচাই হয়, আর C++ টেমপ্লেট যে ঐতিহাসিকভাবে ইনস্ট্যান্সিয়েশনে গিয়ে তবেই ত্রুটি দেখাত সেই সমস্যার সঙ্গে পার্থক্য দেখানো চিত্রবাস্তবায়ন করেব্যবহার করেব্যবহার করেপূর্বশর্তব্যবহার করেব্যবহার করেপূর্বশর্তদিয়ে কনফিগারপূর্বশর্তপূর্বশর্তবাস্তবায়ন করেবাস্তবায়ন করেপ্রতিরোধ করেকারণ হতে পারেপূর্বশর্তবাস্তবায়ন করেদিয়ে কনফিগারব্যবহার করেব্যবহার করেপূর্বশর্তবাস্তবায়ন করেAda-এর জেনেরিক (generic unit)Ada জেনেরিকের contract modelAda (প্রোগ্রামিং ভাষা)জেনেরিক subprogramজেনেরিক প্যাকেজ (generic package)formal type প্যারামিটারformal subprogram প্যারামিটারformal package প্যারামিটারইনস্ট্যান্সিয়েশন (instantiation)formal object (মান প্যারামিটার)ইনস্ট্যান্সিয়েশনের সময়ই ধরা পড়া টেমপ্লেট ত্রুটিC++ টেমপ্লেটGNATAlire

চিত্রে, টানা রেখা সবসময় সত্য এমন সম্পর্ককে এবং ভাঙা রেখা শর্তসাপেক্ষ সম্পর্ককে নির্দেশ করে (শর্তগুলো বিস্তারিত পাতায় প্রতিটি সম্পর্কের ব্যাখ্যায় আছে)। সম্পর্কের সম্পূর্ণ তালিকা (মোট 21, প্রমাণ ও নিশ্চয়তার মাত্রাসহ) এবং প্রধান ধারণাগুলোর সংজ্ঞা জ্ঞান মানচিত্রের বিস্তারিত পাতায় সংগ্রহ করা আছে (জাপানি ভাষায়)। তথ্য: JSON-LD / Turtle

2. এই নিবন্ধের মানচিত্র

আগে পুরো ছবিটা চিত্রে ধরুন। Ada-র generic-কে শুধু «type argument নেওয়া ফিচার» বলে বুঝলে দৃষ্টি অনেক সরু হয়ে যায়। বাস্তবে, যে এককটা পুনর্ব্যবহার করতে চান সেই অনুযায়ী subprogram, package, subprogram parameter, value parameter, formal package parameter জোড়া হয়।

Ada GenericsGeneric SubprogramSwapCount_IfSortGeneric PackageStackStatisticsKV StoreFormal ParametersTypeprivatelimited privaterange boxmod boxdigits boxdelta boxdiscrete boxObjectMax_SizeThresholdSubprogramLess functionEquals functionPredicatePackagewith package P is newGenericDesign IdeasContract ModelStatic CheckingZero-Cost AbstractionSeparate Specification andBody

চিত্রের box মানে Ada-র <> (box compound delimiter)। Mermaid <> আঁকতে পারে না বলে চিত্রে শুধু box লেখা।

এই নিবন্ধ পড়ার ধরন সরল। আগের ভাগে syntax, পরের ভাগে ডিজাইন সিদ্ধান্ত। Ada প্রথমবার পড়লে ছোটখাটো syntax মুখস্থ করার চেষ্টা না করে «কী formal parameter করা হয়েছে» এবং «সেই formal parameter-এ কোন operation অনুমোদিত» — এই দুটোতে নজর রাখুন।

2.1 ছোট পরিভাষা অভিধান

এরপর বারবার আসা শব্দগুলো আগে ইংরেজি ও অর্থের সঙ্গে মিলিয়ে রাখা যাক। জাপানি Ada সাহিত্যে generic-কে প্রায়ই সেই ভাষার নিজস্ব সমতুল্যে লেখা হয়; এই নিবন্ধে আমরা generic subprogram, generic package লিখি, অর্থ একই — generic।

এই নিবন্ধের লেখা ইংরেজি অর্থ
generic unit generic unit generic দিয়ে শুরু হওয়া ঘোষণা। Generic subprogram ও generic package-এর মিলিত নাম
formal parameter generic formal parameter generic ও ঘোষণার body-র মাঝে লেখা, গ্রহণকারী দিকের argument। Type, value, subprogram অথবা package
formal part generic formal part Formal parameter সাজানো অংশটাই। «চুক্তি লেখার জায়গা» বলে পড়লেই চলে
actual parameter generic actual parameter Instantiation-এ সত্যি পাঠানো type, value, subprogram, package
instantiation instantiation new দিয়ে generic unit থেকে সাধারণ subprogram বা package তৈরি
box <> Ada-তে <> চিহ্নের নাম। range <>-এর মতো «নির্দিষ্ট type instantiation-এ ঠিক হবে» বোঝায়
contract model contract model Formal parameter-এ লেখা প্রতিশ্রুতির সীমার মধ্যে body লেখা, body একাই type-check করা Ada-র পদ্ধতি (অধ্যায় ১৩)

মূলে Ada-র লেখা অনুযায়ী range <>, digits <> লিখব, কিন্তু চিত্রে শুধু range box, digits box লেখা। Mermaid <> সহ লেবেল আঁকতে পারে না বলে; অর্থ মূলের সঙ্গে এক। উপরের সারণি অনুযায়ী Ada নিজেই <>-কে box বলে, তাই চিত্রের লেখা Ada পরিভাষার বাইরে নয়।

3. চালানোর পরিবেশ ও কম্পাইল পদ্ধতি

এই নিবন্ধের কোড GNAT 15.x বা তার পরের ধরে নেওয়া। GNAT Ada-র প্রধান compiler, Alire থেকে বসানো যায়। Alire হলো Ada / SPARK-এর package manager; toolchain ব্যবস্থাপনা ও বিল্ডেও লাগে।

gnat --version
# GNAT 15.2.1

GNAT Alire (Ada-র package manager) থেকে alr install gnat_native gprbuild দিয়ে বসিয়ে PATH-এ দিন।

এই নিবন্ধের নমুনা রিপোজিটরিতে এভাবে রাখার কথা।

নমুনার ফাইল বিন্যাসada-generic-programming রিপোজিটরিতে src/snippets-এর নমুনা ফাইলগুলোর অবস্থান।ada-generic-programming/src/snippets/01_swap.ada02_stack.ada03_sort.ada04_statistics.ada05_filter.ada06_kv_store.adaREADME.md

একাধিক compilation unit এক ফাইলে জড়ালে gnatchop দিয়ে ভাগ করে তারপর gnatmake করেন।

mkdir work
cd work
gnatchop ../src/snippets/01_swap.ada
gnatmake -gnata swap_demo
./swap_demo

-gnata assertion চালু করার option। Generic ব্যবহার করতে এটা বাধ্যতামূলক নয়, কিন্তু শেখার নমুনায় contract ও সীমানা শর্ত দেখা সহজ হয়।

gnatchop থেকে চালানো পর্যন্তএকটি .ada ফাইল gnatchop দিয়ে ভাগ করে gnatmake-এ বিল্ড করে চালানোর ধাপ।এক্সিকিউটেবলgnatmakegnatchopডেভেলপারএক্সিকিউটেবলgnatmakegnatchopডেভেলপারএকটি .ada ফাইল দেন.ads / .adb / main-এ ভাগgnatmake -gnata mainbind ও link পর্যন্ত চালায়./mainচালানোর ফল

4. Ada generic-এর মৌলিক মডেল

Ada-র generic মোটামুটি এই তিনটে দিয়ে ভাবা সহজ।

  1. Generic unit লিখুন
  2. generic অংশে formal parameter লিখুন
  3. ব্যবহারকারী দিকে new দিয়ে instantiate করুন
Ada generic-এর মৌলিক মডেলgeneric ঘোষণা, formal parameter, body, এবং new দিয়ে instantiation-এর সম্পর্ক।generic ঘোষণাFormal parameterGeneric bodynew দিয়ে instantiationসাধারণ subprogram বা package হিসেবে ব্যবহারTypeValueSubprogramPackage

উদাহরণ: দুটি মান বিনিময়ের logic generic করলে শুধু type-কে formal parameter করা যায়।

generic
   type Element is private;
procedure Generic_Swap (A, B : in out Element);

এই মুহূর্তে Generic_Swap এখনও ডাকা যায় না। এটা «যেকোনো Element type-এ চলবে এমন বিনিময়ের template»। নির্দিষ্ট type দিলে তবেই সাধারণ procedure হয়।

procedure Swap_Integer is new Generic_Swap (Integer);

চিত্রে সম্পর্ক এমন।

Generic_Swap-এর instantiationএকই Generic_Swap থেকে Integer, Character, My_Record-এর জন্য আলাদা procedure তৈরি।Integer দেওয়াCharacter দেওয়াMy_Record দেওয়াGeneric_Swaptype Element is privateSwap_IntegerSwap_CharacterSwap_My_RecordInteger ভেরিয়েবল বিনিময়Character ভেরিয়েবল বিনিময়My_Record ভেরিয়েবল বিনিময়

গুরুত্বপূর্ণ কথা: template-এর body শুধু Element-এ যে operation চলে সেগুলো দিয়ে লেখা। type Element is private; ঘোষণা করলে assignment বা equality-র মতো মৌলিক operation চলে, কিন্তু ছোট-বড় তুলনা বা arithmetic চলে না। অর্থাৎ generic-এর ঘোষণা নিজেই «এই অংশ কী ধরে নিতে পারে» বলে দেয়।

5. Formal parameter-এর ধরন — Ada generic-এর শব্দভাণ্ডার

Ada generic শুধু type নেয় না। C# বা Java-র সাধারণ generic-এর সঙ্গে এখানেই বড় ফারাক।

Formal parameter-এর চার ধরনType, object বা value, subprogram, এবং package parameter-এর প্রতিনিধি উদাহরণ।generic formal parametersType parameterObject / value parameterSubprogram parameterPackage parametertype Element is privatetype Index is boxtype Real is digits boxMax_Size : PositiveDefault_Value : Elementwith function Less...with procedure Put ...with package P is new ...

চিত্রের box মানে Ada-র <> (box compound delimiter)। Mermaid <> আঁকতে পারে না বলে চিত্রে শুধু box লেখা।

প্রতিনিধি formal parameter সারণিতে এমন।

ধরন উদাহরণ অর্থ
Type parameter type Element is private; যেকোনো definite, non-limited type নেওয়ার মৌলিক রূপ
Limited type parameter type Element is limited private; কপি করা যায় না এমন type-ও নেয়
Discrete type type Index is (<>); Integer বা enumeration — array index-এ চলে এমন type
Signed integer type type Count is range <>; +, -, ছোট-বড় তুলনা ইত্যাদি integer arithmetic ধরে নেওয়া যায়
Modular integer type type Word is mod <>; Bitwise ও modulo-ধর্মী integer
Floating-point type type Real is digits <>; Float, Long_Float, ব্যবহারকারীর floating-point type ইত্যাদি
Fixed-point type type Money is delta <>; Fixed-point arithmetic
Value parameter Max_Size : Positive; Size বা threshold instance অনুযায়ী আটকে দেওয়া
Subprogram with function Predicate (...) return Boolean; Comparison বা predicate — behavior inject করা
Package with package P is new Some_Generic (<>); তৈরি হয়ে যাওয়া generic package-কে অংশ হিসেবে নেওয়া

এই শব্দভাণ্ডার থাকায় Ada-তে «যা খুশি নেবে, ভিতরে বিপজ্জনক কাজ করবে» নয়, «যে type এই operation করতে পারে শুধু সেটাই নেবে» — এই লেখা স্বাভাবিকভাবেই আসে।

6. Generic subprogram — Generic_Swap দিয়ে সবচেয়ে ছোট গঠন

প্রথম উদাহরণ: যেকোনো type-এর দুটি ভেরিয়েবল বিনিময় করা Generic_Swap

6.1 Specification

generic
   type Element is private;
procedure Generic_Swap (A, B : in out Element);

generic-এর পরের অংশ formal parameter। এখানে Element নামের type নেওয়া হচ্ছে। is private মানে generic body থেকে দেখলে সেই type-এর অভ্যন্তরীণ উপস্থাপন জানা নেই।

এই ঘোষণা থেকে দুটো কথা বোঝা যায়।

  • Generic_Swap যেকোনো Element type-এ চলে
  • Body Element-এর অভ্যন্তরীণ গঠন বা ছোট-বড় তুলনার উপর নির্ভর করে না

6.2 Body

procedure Generic_Swap (A, B : in out Element) is
   Temp : constant Element := A;
begin
   A := B;
   B := Temp;
end Generic_Swap;

এই body-তে Element-এ শুধু assignment ব্যবহার করা হয়েছে। A < Bও নেই, A + Bও নেই। তাই Integer, Character, record type, enumeration — assignment চলে এমন type-এ স্বাভাবিকভাবেই চলে।

Swap-এর আগে ও পরেTemp দিয়ে দুটি মান বিনিময়ের ধাপ।কলের পরেকলের আগেA = 20B = 10A = 10B = 20Temp = A

6.3 Instantiation

ব্যবহারকারী দিকে new ব্যবহার করেন।

procedure Swap_Int  is new Generic_Swap (Integer);
procedure Swap_Char is new Generic_Swap (Character);

এতে Swap_IntSwap_Char সাধারণ procedure হিসেবে ডাকা যায়।

with Ada.Text_IO; use Ada.Text_IO;

procedure Swap_Demo is
   generic
      type Element is private;
   procedure Generic_Swap (A, B : in out Element);

   procedure Generic_Swap (A, B : in out Element) is
      Temp : constant Element := A;
   begin
      A := B;
      B := Temp;
   end Generic_Swap;

   procedure Swap_Int is new Generic_Swap (Integer);

   X : Integer := 10;
   Y : Integer := 20;
begin
   Put_Line ("Before: X=" & Integer'Image (X) & ", Y=" & Integer'Image (Y));
   Swap_Int (X, Y);
   Put_Line ("After : X=" & Integer'Image (X) & ", Y=" & Integer'Image (Y));
end Swap_Demo;

চালালে ছবি এমন।

Before: X= 10, Y= 20
After : X= 20, Y= 10

এখানে Swap_Int (X, Y);-এ Float ভেরিয়েবল দেওয়া যায় না। Swap_Int Integer-এর জন্য instantiate করা সাধারণ procedure। Generic «যা খুশি ঢোকে এমন গর্ত» নয়, «প্রতিটি type-এ নিরাপদ নির্দিষ্ট জিনিস তৈরির ব্যবস্থা» — এভাবে ধরলে বোঝা সহজ।

7. Generic package — type ও value-কে parameter করা

একটি subprogram নয়, একাধিক operation ও অভ্যন্তরীণ অবস্থা একসঙ্গে পুনর্ব্যবহার করতে চাইলে generic package ব্যবহার করেন। প্রতিনিধি উদাহরণ stack।

Stack-এর ক্ষেত্রে element type ও সর্বোচ্চ size বদলালেই মৌলিক logic একই থাকে।

Generic_Stack-এর parameter ও instanceElement_Type ও Max_Size নিয়ে আলাদা stack instance তৈরি।Generic_StackElement_TypeMax_SizePush / Pop / Size / Is_Empty / Is_FullInt_StackElement=IntegerMax_Size=5Float_StackElement=FloatMax_Size=3String_StackElement=Unbounded_StringMax_Size=20

7.1 Specification

generic
   type Element_Type is private;
   Max_Size : Positive;
package Generic_Stack is
   procedure Push (Item : Element_Type);
   function Pop return Element_Type;
   function Is_Empty return Boolean;
   function Is_Full  return Boolean;
   function Size return Natural;

   Stack_Overflow  : exception;
   Stack_Underflow : exception;
end Generic_Stack;

এখানে দুই ধরনের formal parameter ব্যবহার করা হয়েছে।

  • Element_Type type parameter
  • Max_Size value parameter

Max_Size Positive, তাই 0 বা তার কম size দিয়ে instantiate করা যায় না। Value parameter-এও type দিয়ে বাধা দেওয়া যায়।

7.2 Body

package body Generic_Stack is
   subtype Index_Type is Positive range 1 .. Max_Size;
   type Storage_Type is array (Index_Type) of Element_Type;

   Data : Storage_Type;
   Top  : Natural := 0;

   procedure Push (Item : Element_Type) is
   begin
      if Top = Max_Size then
         raise Stack_Overflow;
      end if;

      Top := Top + 1;
      Data (Top) := Item;
   end Push;

   function Pop return Element_Type is
      Result : Element_Type;
   begin
      if Top = 0 then
         raise Stack_Underflow;
      end if;

      Result := Data (Top);
      Top := Top - 1;
      return Result;
   end Pop;

   function Is_Empty return Boolean is
   begin
      return Top = 0;
   end Is_Empty;

   function Is_Full return Boolean is
   begin
      return Top = Max_Size;
   end Is_Full;

   function Size return Natural is
   begin
      return Top;
   end Size;
end Generic_Stack;

এই package body-তে গুরুত্বপূর্ণ কথা: DataTop প্রতিটি instance-এ আলাদা করে তৈরি হয়।

package Int_Stack   is new Generic_Stack (Integer, 5);
package Float_Stack is new Generic_Stack (Float,   3);

এই দুটো একই template থেকে তৈরি, কিন্তু অভ্যন্তরীণ অবস্থা শেয়ার করে না।

Instance অনুযায়ী আলাদা অবস্থাInt_Stack ও Float_Stack একই template থেকে এলেও অবস্থা শেয়ার করে না।Float_Stack-এর অবস্থাTopData : Float arrayInt_Stack-এর অবস্থাTopData : Integer arrayGeneric_StackInt_StackFloat_Stack

7.3 Stack-এর অবস্থা পরিবর্তন

Stack-কে state machine হিসেবে দেখলে বোঝা সহজ।

Stack-এর অবস্থা পরিবর্তনEmpty, NonEmpty, Full এবং overflow বা underflow-এর state diagram।PushPush / PopPop দিয়ে শেষ element বের করাPush-এ Max_Size-এ পৌঁছানোPopPushPopEmptyNonEmptyFullOverflowUnderflow

7.4 ব্যবহারের উদাহরণ

with Ada.Text_IO; use Ada.Text_IO;

procedure Stack_Demo is
   generic
      type Element_Type is private;
      Max_Size : Positive;
   package Generic_Stack is
      procedure Push (Item : Element_Type);
      function Pop return Element_Type;
      function Is_Empty return Boolean;
      function Is_Full  return Boolean;
      function Size return Natural;
      Stack_Overflow  : exception;
      Stack_Underflow : exception;
   end Generic_Stack;

   package body Generic_Stack is
      subtype Index_Type is Positive range 1 .. Max_Size;
      type Storage_Type is array (Index_Type) of Element_Type;

      Data : Storage_Type;
      Top  : Natural := 0;

      procedure Push (Item : Element_Type) is
      begin
         if Top = Max_Size then
            raise Stack_Overflow;
         end if;

         Top := Top + 1;
         Data (Top) := Item;
      end Push;

      function Pop return Element_Type is
         Result : Element_Type;
      begin
         if Top = 0 then
            raise Stack_Underflow;
         end if;

         Result := Data (Top);
         Top := Top - 1;
         return Result;
      end Pop;

      function Is_Empty return Boolean is (Top = 0);
      function Is_Full  return Boolean is (Top = Max_Size);
      function Size     return Natural is (Top);
   end Generic_Stack;

   package Int_Stack is new Generic_Stack (Integer, 5);
begin
   Int_Stack.Push (10);
   Int_Stack.Push (20);
   Int_Stack.Push (30);

   Put_Line ("Size=" & Natural'Image (Int_Stack.Size));
   Put_Line ("Pop =" & Integer'Image (Int_Stack.Pop));
   Put_Line ("Pop =" & Integer'Image (Int_Stack.Pop));
   Put_Line ("Size=" & Natural'Image (Int_Stack.Size));
end Stack_Demo;

অধ্যায় ৩-এর মতোই বিল্ড করে চালান।

gnatchop ../src/snippets/02_stack.ada
gnatmake -gnata stack_demo
./stack_demo
Size= 3
Pop = 30
Pop = 20
Size= 1

=-এর ডানে একটি ফাঁকা থাকে কারণ integer type-এর 'Image অঋণাত্মক মানের আগে একটি space বসায় — এটা ভাষার নিয়ম। Push তিনবার, Pop দুবার, তাই শেষ Size 1। Stack পূর্ণ (এই উদাহরণে Max_Size 5টি) অবস্থায় আরও Push ডাকলে Int_Stack.Stack_Overflow, খালি অবস্থায় Pop ডাকলে Int_Stack.Stack_Underflow উঠে।

Generic package বাস্তবে «ছোট container», «fixed-length buffer», «ring buffer», «log-এর queue», «hardware abstraction layer»-এ ভালো কাজ করে। বিশেষ করে Ada-তে size runtime-এ নাড়িয়ে না নিয়ে type বা value parameter হিসেবে statically আটকে দেওয়া ডিজাইন উচ্চ নির্ভরযোগ্য সিস্টেমের সঙ্গে মিলে যায়।

8. Formal subprogram parameter — behavior inject করা

শুধু type নিলেও এখনও যা প্রকাশ করা যায় না তা আছে। যেমন sort-এ element type ছাড়াও «কাকে আগে সাজাবেন» — comparison logic লাগে।

Ada-তে এই comparison function-কে generic-এর formal parameter করা যায়।

Generic_Insertion_Sort-এর formal parameterItem_Type, Index, Item_Array এবং comparison function-এর সম্পর্ক।Generic_Insertion_SortItem_TypeIndexItem_ArrayComparison functionমানক comparison ব্যবহারGreater দিয়ে descendingনিজস্ব ক্রম দেওয়া

8.1 Specification

generic
   type Item_Type is private;
   type Index is (<>);
   type Item_Array is array (Index range <>) of Item_Type;
   with function "<" (Left, Right : Item_Type) return Boolean is <>;
procedure Generic_Insertion_Sort (Items : in out Item_Array);

এখানে চারটি formal parameter আছে।

  1. Item_Type: array element-এর type
  2. Index: array index-এর type
  3. Item_Array: আসল array type
  4. "<": comparison function

type Index is (<>); discrete type নেয়। Integer ছাড়াও enumeration নেওয়া যায়। Array index-এ শুধু Positive নয়, Day-এর মতো enumerationও চলে — এটাই Ada-র ধরন।

with function "<" ... is <>;-এর is <> মানে actual parameter বাদ দিলে দৃশ্যমান মানক operator বা মানানসই function ব্যবহার হবে। অর্থাৎ Integer-এর মতো যে type-এ ইতিমধ্যে < আছে, comparison function না লিখলেও চলে।

8.2 Body

procedure Generic_Insertion_Sort (Items : in out Item_Array) is
   J   : Index;
   Key : Item_Type;
begin
   if Items'Length <= 1 then
      return;
   end if;

   for I in Index'Succ (Items'First) .. Items'Last loop
      Key := Items (I);
      J := I;

      while J > Items'First and then Key < Items (Index'Pred (J)) loop
         Items (J) := Items (Index'Pred (J));
         J := Index'Pred (J);
      end loop;

      Items (J) := Key;
   end loop;
end Generic_Insertion_Sort;

Insertion sort বড় array-এ মানায় না, কিন্তু generic বোঝাতে মানায়। শুধু comparison function বদলে একই loop structure ascending-এও descending-এও চলে।

Insertion sort-এর প্রবাহKey তুলে তুলনা করে সরিয়ে ঢোকানোর loop।YesNoNoYesঅসাজানো arrayবাম দিক থেকে ক্রমে Key তোলাKey কি ঠিক আগের element-এর আগে?আগের element ডানে সরানোKey ঢোকানোশেষ পর্যন্ত হয়েছে?সাজানো array

8.3 একই body থেকে ascending ও descending

type Int_Array is array (Positive range <>) of Integer;

procedure Sort_Asc is new Generic_Insertion_Sort
  (Item_Type  => Integer,
   Index      => Positive,
   Item_Array => Int_Array);

function Greater (Left, Right : Integer) return Boolean is
  (Left > Right);

procedure Sort_Desc is new Generic_Insertion_Sort
  (Item_Type  => Integer,
   Index      => Positive,
   Item_Array => Int_Array,
   "<"        => Greater);

Sort_Asc মানক < ব্যবহার করে। অন্যদিকে Sort_Desc "<" => Greater দিয়ে comparison function বদলে দেয়।

একই body থেকে ascending ও descendingমানক comparison এবং Greater দিয়ে একই ডেটার দুই রকম সাজানো।99, 3, 47, 12Sort_Ascমানক comparisonSort_DescGreater-কে comparison হিসেবে দেওয়া3, 12, 47, 9999, 47, 12, 3

এই ব্যবস্থা C++-এ comparison function object template argument হিসেবে দেওয়া ডিজাইন, বা Rust-এ trait bound দিয়ে ক্রম চাওয়া ডিজাইনের কাছাকাছি। তবে Ada-তে formal subprogram parameter হিসেবে «এই আকারের function দেবেন» স্পষ্ট করে লেখা হয়।

8.4 চালানোর উদাহরণ

অধ্যায় ১৮-এর কাঠামো অনুযায়ী Generic_Insertion_Sort আলাদা ফাইলে (generic_insertion_sort.ads / .adb) রাখলে কলকারী দিক এমন হয়।

with Ada.Text_IO;            use Ada.Text_IO;
with Generic_Insertion_Sort;

procedure Sort_Demo is
   type Int_Array is array (Positive range <>) of Integer;

   function Greater (Left, Right : Integer) return Boolean is
     (Left > Right);

   procedure Sort_Asc is new Generic_Insertion_Sort
     (Item_Type  => Integer,
      Index      => Positive,
      Item_Array => Int_Array);

   procedure Sort_Desc is new Generic_Insertion_Sort
     (Item_Type  => Integer,
      Index      => Positive,
      Item_Array => Int_Array,
      "<"        => Greater);

   procedure Show (Label : String; Items : Int_Array) is
   begin
      Put (Label);
      for V of Items loop
         Put (Integer'Image (V));
      end loop;
      New_Line;
   end Show;

   Asc  : Int_Array := (99, 3, 47, 12);
   Desc : Int_Array := (99, 3, 47, 12);
begin
   Sort_Asc (Asc);
   Sort_Desc (Desc);
   Show ("Asc :", Asc);
   Show ("Desc:", Desc);
end Sort_Demo;
gnatchop ../src/snippets/03_sort.ada
gnatmake -gnata sort_demo
./sort_demo
Asc : 3 12 47 99
Desc: 99 47 12 3

একই Generic_Insertion_Sort body থেকে তৈরি দুটি procedure শুধু comparison বদলে উল্টো ক্রম হয়েছে — সেটা দেখা যায়। প্রতিটি মানের আগের ফাঁকাটা এই জন্য যে, integer type-এর 'Image অঋণাত্মক মানের আগে একটি space বসায়।

9. Type category — private-এর চেয়ে নির্দিষ্ট contract লেখা

type T is private; সুবিধাজনক, কিন্তু যা খুশি করা যায় না। private type-এ arithmetic বা ছোট-বড় তুলনা স্বাভাবিকভাবে ধরে নেওয়া যায় না। তাই Ada-তে formal type parameter-এ category নির্দিষ্ট করা যায়।

Formal type-এর categoryprivate থেকে digits box পর্যন্ত type category-র শাখা।Formal Typeprivatelimited privatediscrete box: discrete typerange box: signed integermod box: modular integerdigits box: floating-pointdelta box: fixed-pointaccess typeEnumerationInteger typeFloatLong_Floatব্যবহারকারীর floating-point type

চিত্রের box মানে Ada-র <> (box compound delimiter)। Mermaid <> আঁকতে পারে না বলে চিত্রে শুধু box লেখা।

9.1 Category নির্দিষ্ট করলে কী লাভ

যেমন গড় বা variance হিসাব করতে যোগ, বিয়োগ, গুণ, ভাগ লাগে। private type-এ এই operation ধরে নেওয়া যায় না। তাই floating-point type-এ সীমাবদ্ধ করা হয়।

generic
   type Real is digits <>;
   type Real_Array is array (Positive range <>) of Real;
package Generic_Statistics is
   function Mean (Values : Real_Array) return Real;
   function Variance (Values : Real_Array) return Real;
end Generic_Statistics;

type Real is digits <>; দিয়ে Real যে floating-point type সেটা বোঝা যায়। তাই generic body-তে +, -, *, / ব্যবহার করা যায়।

9.2 Body

package body Generic_Statistics is
   function Mean (Values : Real_Array) return Real is
      Sum : Real := 0.0;
   begin
      if Values'Length = 0 then
         return 0.0;
      end if;

      for V of Values loop
         Sum := Sum + V;
      end loop;

      return Sum / Real (Values'Length);
   end Mean;

   function Variance (Values : Real_Array) return Real is
      M   : constant Real := Mean (Values);
      Sum : Real := 0.0;
   begin
      if Values'Length = 0 then
         return 0.0;
      end if;

      for V of Values loop
         declare
            D : constant Real := V - M;
         begin
            Sum := Sum + D * D;
         end;
      end loop;

      return Sum / Real (Values'Length);
   end Variance;
end Generic_Statistics;

9.3 FloatLong_Float-এ ব্যবহার

type Float_Array is array (Positive range <>) of Float;
type Long_Array  is array (Positive range <>) of Long_Float;

package Float_Stats is new Generic_Statistics (Float, Float_Array);
package Long_Stats  is new Generic_Statistics (Long_Float, Long_Array);

একই পরিসংখ্যান ভিন্ন নির্ভুলতার floating-point type-এ পুনর্ব্যবহার করা যায়।

Generic_Statistics-এর instantiationFloat, Long_Float ও ব্যবহারকারীর Real-এ একই পরিসংখ্যান।Generic_StatisticsReal is digits boxFloat_StatsLong_StatsMy_Real_StatsFloat-এ Mean / VarianceLong_Float-এ Mean / Varianceব্যবহারকারীর Real-এ Mean / Variance

9.4 চালানোর উদাহরণ

with Ada.Text_IO;        use Ada.Text_IO;
with Ada.Float_Text_IO;  use Ada.Float_Text_IO;
with Generic_Statistics;

procedure Statistics_Demo is
   type Float_Array is array (Positive range <>) of Float;

   package Float_Stats is new Generic_Statistics (Float, Float_Array);

   Samples : constant Float_Array := (1.0, 2.0, 3.0, 4.0);
begin
   Put ("Mean     = ");
   Put (Float_Stats.Mean (Samples), Fore => 1, Aft => 3, Exp => 0);
   New_Line;

   Put ("Variance = ");
   Put (Float_Stats.Variance (Samples), Fore => 1, Aft => 3, Exp => 0);
   New_Line;
end Statistics_Demo;
gnatchop ../src/snippets/04_statistics.ada
gnatmake -gnata statistics_demo
./statistics_demo
Mean     = 2.500
Variance = 1.250

Ada.Float_Text_IO হলো Ada.Text_IO.Float_IO-কে Float-এ instantiate করা standard library; Exp => 0 দিলে exponential নয়, সাধারণ দশমিক লেখা হয়। Aft => 3 দশমিকের পরের অঙ্ক। মনে রাখুন, এই Variance নমুনা variance নয়, population variance (Values'Length দিয়ে ভাগ)।

9.5 Category নির্দিষ্টকরণ «type-level specification»

Category নির্দিষ্টকরণ শুধু compiler চুপ করানোর syntax নয়। পাঠককেও «এই অংশ কী চায়» বলে দেওয়া specification।

যে logic লিখতে চান যে formal type মানায় কারণ
বিনিময়, রাখা, বের করা private Assignment চললেই হয়
কপি করা যায় না এমন resource ব্যবস্থাপনা limited private Assignment ধরে নেয় না
Array index, enumeration অবস্থা ঘোরা (<>) First, Last, Succ, Pred চলে
Integer যোগফল, counter range <> Integer arithmetic ধরে নেওয়া যায়
Bitmask, circular counter mod <> Modular arithmetic ধরে নেওয়া যায়
গড়, variance, সংখ্যাগত হিসাব digits <> Floating-point arithmetic ধরে নেওয়া যায়
টাকা, নিয়ন্ত্রণ মান ইত্যাদি নির্দিষ্ট নির্ভুলতা delta <> Fixed-point arithmetic ধরে নেওয়া যায়

10. Predicate inject করা — Count_If-কে Ada-র মতো লেখা

Formal subprogram parameter শুধু comparison নয়, predicate-এও লাগে। Predicate মানে একটি মান নিয়ে Boolean ফেরানো function।

C#-এর Func<T, bool>, Java-র Predicate<T>, C++-এর lambda বা function object-এর কাছাকাছি ভূমিকা Ada-তে generic-এর formal subprogram হিসেবে লেখা যায়।

10.1 Specification

generic
   type Element is private;
   type Index is (<>);
   type Array_Type is array (Index range <>) of Element;
   with function Predicate (Item : Element) return Boolean;
function Generic_Count_If (Arr : Array_Type) return Natural;

এখানে Predicate-এ is <> দেওয়া হয়নি। মানকভাবে দৃশ্যমান কোনো predicate function থাকে না, তাই ব্যবহারকারীকে অবশ্যই দিতে হবে — এই ডিজাইন।

10.2 Body

function Generic_Count_If (Arr : Array_Type) return Natural is
   Count : Natural := 0;
begin
   for Item of Arr loop
      if Predicate (Item) then
         Count := Count + 1;
      end if;
   end loop;

   return Count;
end Generic_Count_If;

প্রবাহ সরল।

Count_If-এর প্রবাহArray ঘুরে Predicate সত্য হলে Count বাড়ানো।TrueFalseArrayপ্রতিটি element ঘোরাPredicate(Item)?Count বাড়ানোকিছুই নাপরের element-এCount ফেরানো

10.3 জোড় গণনা ও threshold গণনা

type Int_Array is array (Positive range <>) of Integer;

function Is_Even (N : Integer) return Boolean is
  (N mod 2 = 0);

function Is_Large (N : Integer) return Boolean is
  (N > 50);

function Count_Even is new Generic_Count_If
  (Element    => Integer,
   Index      => Positive,
   Array_Type => Int_Array,
   Predicate  => Is_Even);

function Count_Large is new Generic_Count_If
  (Element    => Integer,
   Index      => Positive,
   Array_Type => Int_Array,
   Predicate  => Is_Large);

একই traversal logic থেকে শুধু শর্ত আলাদা দুটি function তৈরি হয়।

Predicate বদলে দুটি ফাংশনএকই Generic_Count_If থেকে জোড় ও threshold গণনা।Generic_Count_IfCount_EvenPredicate = Is_EvenCount_LargePredicate = Is_Large12, 7, 88, 3, 56, 91, 44, 19, 62জোড় সংখ্যার সংখ্যা50-এর চেয়ে বড়গুলোর সংখ্যা

এই উদাহরণে array traversal, counter ব্যবস্থাপনা, ফল ফেরানো সবই সাধারণ। অন্যদিকে «কী গুনবেন» শুধু function হিসেবে inject করা। Ada-তে higher-order ডিজাইনের মৌলিক রূপ এটাই।

10.4 চালানোর উদাহরণ

with Ada.Text_IO;       use Ada.Text_IO;
with Generic_Count_If;

procedure Count_If_Demo is
   type Int_Array is array (Positive range <>) of Integer;

   function Is_Even (N : Integer) return Boolean is
     (N mod 2 = 0);

   function Is_Large (N : Integer) return Boolean is
     (N > 50);

   function Count_Even is new Generic_Count_If
     (Element    => Integer,
      Index      => Positive,
      Array_Type => Int_Array,
      Predicate  => Is_Even);

   function Count_Large is new Generic_Count_If
     (Element    => Integer,
      Index      => Positive,
      Array_Type => Int_Array,
      Predicate  => Is_Large);

   Data : constant Int_Array := (12, 7, 88, 3, 56, 91, 44, 19, 62);
begin
   Put_Line ("Even  =" & Natural'Image (Count_Even (Data)));
   Put_Line ("Large =" & Natural'Image (Count_Large (Data)));
end Count_If_Demo;
gnatchop ../src/snippets/05_filter.ada
gnatmake -gnata count_if_demo
./count_if_demo
Even  = 5
Large = 4

Data-র 9টি element-এর মধ্যে জোড় 12, 88, 56, 44, 62 — 5টি; 50-এর চেয়ে বড় 88, 56, 91, 62 — 4টি।

11. একাধিক parameter জোড়া — সাধারণ key-value store

বাস্তব অংশে শুধু একটি type parameter-এ কাজ সারা হয় না প্রায়ই। Key ও value-এর type, key তুলনার পদ্ধতি, সর্বোচ্চ সংখ্যা — একাধিক শর্ত জোড়াতে হয়।

এখানে fixed-length, সরল key-value store উদাহরণ।

Generic_KV_Store-এর parameterKey, Value, equality function, Max_Entries এবং ব্যবহারের জায়গা।Generic_KV_StoreKey_TypeValue_TypeKey মিলানোর functionMax_EntriesPut / Get / Containsসেটিং-এর storeছোট cacheEmbedded-এর fixed-length dictionary

11.1 Specification

generic
   type Key_Type is private;
   type Value_Type is private;
   with function "=" (Left, Right : Key_Type) return Boolean is <>;
   Max_Entries : Positive := 50;
package Generic_KV_Store is
   procedure Put (Key : Key_Type; Val : Value_Type);
   function Get (Key : Key_Type) return Value_Type;
   function Contains (Key : Key_Type) return Boolean;

   Key_Not_Found : exception;
   Store_Full    : exception;
end Generic_KV_Store;

এই package-এ চারটি formal parameter আছে।

Parameter ধরন ভূমিকা
Key_Type Type Key-এর type
Value_Type Type Value-এর type
"=" Subprogram Key মিলানোর পরীক্ষা
Max_Entries Value সর্বোচ্চ entry সংখ্যা

Max_Entries-এ := 50 দিয়ে default দেওয়া। তাই আলাদা করে না দিলে 50টি entry-র store হয়।

11.2 Body

package body Generic_KV_Store is
   subtype Index_Type is Positive range 1 .. Max_Entries;

   type Key_Array   is array (Index_Type) of Key_Type;
   type Value_Array is array (Index_Type) of Value_Type;
   type Used_Array  is array (Index_Type) of Boolean;

   Keys   : Key_Array;
   Values : Value_Array;
   Used   : Used_Array := (others => False);

   function Find_Index (Key : Key_Type) return Natural is
   begin
      for I in Index_Type loop
         if Used (I) and then Keys (I) = Key then
            return I;
         end if;
      end loop;

      return 0;
   end Find_Index;

   function Find_Free return Natural is
   begin
      for I in Index_Type loop
         if not Used (I) then
            return I;
         end if;
      end loop;

      return 0;
   end Find_Free;

   procedure Put (Key : Key_Type; Val : Value_Type) is
      Pos : Natural := Find_Index (Key);
   begin
      if Pos = 0 then
         Pos := Find_Free;

         if Pos = 0 then
            raise Store_Full;
         end if;

         Used (Pos) := True;
         Keys (Pos) := Key;
      end if;

      Values (Pos) := Val;
   end Put;

   function Get (Key : Key_Type) return Value_Type is
      Pos : constant Natural := Find_Index (Key);
   begin
      if Pos = 0 then
         raise Key_Not_Found;
      end if;

      return Values (Pos);
   end Get;

   function Contains (Key : Key_Type) return Boolean is
   begin
      return Find_Index (Key) /= 0;
   end Contains;
end Generic_KV_Store;

এই বাস্তবায়ন linear search, তাই বিপুল ডেটার জন্য নয়। তবে fixed-length, ছোট আকার, dynamic memory allocation নেই — এই ধর্ম যেখানে জরুরি, সেখানে ব্যবহারযোগ্য রূপ।

Put ও Get-এর ধাপবিদ্যমান key আপডেট বনাম নতুন key ঢোকানোর sequence।Keys/Values/UsedGeneric_KV_Store instanceকলকারী দিকKeys/Values/UsedGeneric_KV_Store instanceকলকারী দিকalt[বিদ্যমান key আছে][নতুন key]Put(Key, Value)Find_Index(Key)Values(Pos) := ValueFind_FreeKeys(Pos) := KeyValues(Pos) := ValueUsed(Pos) := TrueGet(Key)Find_Index(Key)PosValues(Pos)

11.3 Instantiation-এর উদাহরণ

with Ada.Text_IO;           use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Generic_KV_Store;

procedure KV_Demo is
   package Int_String_Store is new Generic_KV_Store
     (Key_Type    => Integer,
      Value_Type  => Unbounded_String,
      Max_Entries => 10);
begin
   Int_String_Store.Put (1, To_Unbounded_String ("Ada"));
   Int_String_Store.Put (2, To_Unbounded_String ("SPARK"));

   if Int_String_Store.Contains (1) then
      Put_Line ("1 => " & To_String (Int_String_Store.Get (1)));
   else
      Put_Line ("1 => (not found)");
   end if;

   --  বিদ্যমান key-তে Put overwrite করে
   Int_String_Store.Put (1, To_Unbounded_String ("Ada 2022"));
   Put_Line ("1 => " & To_String (Int_String_Store.Get (1)));

   if Int_String_Store.Contains (9) then
      Put_Line ("9 => " & To_String (Int_String_Store.Get (9)));
   else
      Put_Line ("9 => (not found)");
   end if;
end KV_Demo;
gnatchop ../src/snippets/06_kv_store.ada
gnatmake -gnata kv_demo
./kv_demo
1 => Ada
1 => Ada 2022
9 => (not found)

Contains দিয়ে অস্তিত্ব না দেখে Get ডাকলে, key না থাকলে Key_Not_Found উঠে। উপরের মতো Contains দিয়ে শাখা করুন, অথবা exception handler লিখুন — দুইয়ের একটা বেছে নিন।

"=" বাদ দেওয়া হয়েছে। Integer-এ মানক equality operator আছে, is <> দিয়ে সেটাই ব্যবহৃত হয়।

Key যদি বড়-ছোট হাত উপেক্ষা করা string হয়, নিজস্ব equality function দেওয়া যায়।

function Same_Key (Left, Right : Unbounded_String) return Boolean is
  (To_Lower (To_String (Left)) = To_Lower (To_String (Right)));

package String_Key_Store is new Generic_KV_Store
  (Key_Type    => Unbounded_String,
   Value_Type  => Integer,
   "="         => Same_Key,
   Max_Entries => 100);

12. Formal package parameter — generic-কে আরও কম্পোনেন্ট হিসেবে জোড়া

Ada generic-এ package নিজেকে formal parameter করা যায়। এতে «কোনো generic package থেকে তৈরি instance»-কে অন্য generic-এর ইনপুট হিসেবে ধরা যায়।

Formal package parameterGeneric_Stack instance-কে Generic_Stack_Logger-এ দেওয়া।Generic_StackInt_StackGeneric_Stack_LoggerInt_Stack_Logger_Instance

12.1 Stack নেওয়া logger

যেমন আগের Generic_Stack-এর instance নিয়ে তার size দেখানো logger বানানো যাক।

generic
   with package Stack is new Generic_Stack (<>);
package Generic_Stack_Logger is
   procedure Print_Size;
end Generic_Stack_Logger;

Body এমন।

with Ada.Text_IO; use Ada.Text_IO;

package body Generic_Stack_Logger is
   procedure Print_Size is
   begin
      Put_Line ("Stack size =" & Natural'Image (Stack.Size));
   end Print_Size;
end Generic_Stack_Logger;

ব্যবহারকারী দিকে আগে stack বানিয়ে সেই stack logger-এ দেন।

package Int_Stack is new Generic_Stack
  (Element_Type => Integer,
   Max_Size     => 10);

package Int_Stack_Logger is new Generic_Stack_Logger
  (Stack => Int_Stack);

এই ডিজাইনে generic অংশগুলোকে একে অপরের সঙ্গে জোড়া যায়।

Generic-কে স্তরে জোড়াপ্রথম স্তরে stack, দ্বিতীয় স্তরে logger।দ্বিতীয় স্তরপ্রথম স্তরInt_Stack_LoggerGeneric_Stack_LoggerInt_StackGeneric_StackPrint_Size

C++-এর template template parameter-এর কাছাকাছি ব্যবহার, কিন্তু Ada-তে «এই generic package-এর instance নেবে» স্পষ্ট করে লেখা যায়। বড় Ada কোডে container, algorithm, log, পরীক্ষা, test সহায়তা আলাদা করে জোড়াতে সুবিধা হয়।

13. Contract Model — Ada generic-এর সবচেয়ে জরুরি ধারণা

Ada generic বুঝতে contract model জরুরি।

Generic-এর body শুধু formal parameter যে operation-এর প্রতিশ্রুতি দিয়েছে সেগুলো দিয়ে লিখতে হয়। যেমন শুধু type Element is private; ঘোষণা করে Element-এ < ব্যবহার করা যায় না। < চাইলে formal subprogram হিসেবে স্পষ্ট করতে হয়, অথবা type category আরও নির্দিষ্ট করতে হয়।

Contract model-এর পরীক্ষাFormal part-এর চুক্তির ভিতরে body check, instantiation-এ actual check।generic formal partচুক্তিgeneric bodyচুক্তির সীমায় বাস্তবায়নBody একাই type-checkInstantiationactual parametersআসল type / function / valueActual parameter চুক্তি পূরণ করে কি নাসাধারণ package / subprogram

এই ডিজাইনে generic-এর ব্যবহারকারীই নয়, generic লেখার দিকও রক্ষা পায়।

13.1 C++ template-এর সঙ্গে দেখার ফারাক

C++ template শক্তিশালী, কিন্তু historically «template body instantiate করলে তবেই error ওঠে» — এই ধর্ম ছিল। C++20-এর concepts সেটা উন্নত করেছে, তবে Ada generic শুরু থেকেই চুক্তি স্পষ্ট করার মডেল।

Ada ও C++ template-এর দেখাAda আগে contract লেখে, C++ historically instantiation-এ error দেখায়।C++ templatesinstantiation-এ প্রয়োজনীয় expression নির্দিষ্ট হয়template body লেখাconcepts দিয়ে বাধা স্পষ্ট করা যায়Adabody চুক্তির ভিতরে checkformal part-এ চুক্তি লেখাinstantiation-এ actual check

Java বা C#-এর generic-এ reference type, constraint, type erasure, runtime উপস্থাপনের সম্পর্ক ডিজাইনের কেন্দ্র। অন্যদিকে Ada-র generic compile-time-এ নির্দিষ্ট instance তৈরির ধারণার দিকে ঝোঁকে।

দৃষ্টিভঙ্গি Ada C++ Java Rust
চুক্তি লেখার ধরন formal part-এ type, value, function, package লেখা templates / concepts Type parameter ও bounds trait bounds
Body-র check Formal parameter-এর চুক্তির ভিতরে Instantiation-এ নির্দিষ্টকরণই মূল bounds-এর ভিতরে trait bounds-এর ভিতরে
Runtime খরচ Static resolutionই মূল Static generationই মূল Type erasure-এর প্রভাব Monomorphizationই মূল
Value parameter আছে আছে সীমিত const generics
Subprogram-কে formal parameter করা আছে Function object ইত্যাদি দিয়ে Lambda / function-type interface Closure / function / trait
Package-কে formal parameter করা আছে Template template ইত্যাদি নেই Module গঠন আলাদা বিষয়

ছোটখাটো ভাষা ফিচার আলাদা, কিন্তু Ada-র বৈশিষ্ট্য «চুক্তি syntax হিসেবে আগে লেখা»।

14. বাস্তবে ডিজাইন সিদ্ধান্ত — কী generic করা উচিত

Generic সুবিধাজনক, কিন্তু যা খুশি generic করলেই ভালো হয় না। বাস্তবে এভাবে সিদ্ধান্ত নিলে ব্যর্থতা কম।

কী generic করবেন তার সিদ্ধান্তType, value, subprogram, package-এর মধ্যে বেছে নেওয়ার প্রশ্নমালা।YesNoYesNoYesNoYesNoপুনর্ব্যবহার করতে চাওয়া logic আছেশুধু type আলাদা?Type parameter ভাবাSize বা threshold-ও আলাদা?Value parameter যোগতুলনা বা বিচারের behavior আলাদা?Formal subprogram যোগঅভ্যন্তরীণ অবস্থা বা API একত্র করতে চান?Generic packageসাধারণ subprogramই যথেষ্ট

14.1 Generic subprogram যেখানে মানায়

Generic subprogram অবস্থাহীন algorithm-এ মানায়।

  • Swap
  • Sort
  • Count_If
  • Find
  • Map-ধর্মী রূপান্তর
  • Min / Max

Algorithm-এর body ছোট, ইনপুট ও আউটপুট স্পষ্ট হলে package-এর চেয়ে subprogram পড়া সহজ।

14.2 Generic package যেখানে মানায়

Generic package type-এর সঙ্গে একাধিক operation বা অভ্যন্তরীণ অবস্থা রাখতে চাইলে মানায়।

  • Fixed-length stack
  • Ring buffer
  • ছোট dictionary
  • পরিসংখ্যানের সেট
  • Device অনুযায়ী I/O abstraction
  • এককসহ সংখ্যা type-এর operation সেট

বিশেষ করে Ada-তে package specification প্রকাশ্য API, package body বাস্তবায়ন — এই আলাদা থাকা থাকায় generic package «type-safe module template» হিসেবে ব্যবহার করা যায়।

Generic package-এর spec ও bodyFormal part চুক্তি, spec প্রকাশ্য API, body লুকানো বাস্তবায়ন।লুকানোpackage specপ্রকাশ্য APIব্যবহারকারী দিকpackage bodyঅভ্যন্তরীণ বাস্তবায়নgeneric formal parttype / value / function-এর চুক্তি

14.3 Formal parameter কম করে শুরু করুন

Formal parameter বাড়িয়ে ফেললে instantiation পড়া কঠিন হয়। প্রথমে ন্যূনতম রাখুন, বদলাবার কারণ দেখা দিলে বাড়ান — সেটাই নিরাপদ।

-- পড়া কঠিন হয়ে ওঠার উদাহরণ
package X is new Generic_Foo
  (A, B, C, D, E, F, G);

-- named association দিয়ে উদ্দেশ্য রাখা
package X is new Generic_Foo
  (Element_Type => Integer,
   Index_Type   => Positive,
   Buffer_Size  => 128,
   "<"          => Less);

Ada-তে instantiation-এ named association ব্যবহার করা যায়। Generic-এ ডিজাইনের জরুরি জায়গা instantiation-এ দেখা যায়, তাই বাস্তব কোডে named করে লেখা রক্ষণাবেক্ষণে সহজ হয় প্রায়ই।

15. যেখানে প্রায়ই হোঁচট

Ada generic শক্তিশালী, কিন্তু শুরুতে যেখানে হোঁচট লাগে তা আছে।

15.1 private type-এ ছোট-বড় তুলনা চলে না

এমন body লেখা যায় না।

generic
   type Element is private;
function Bad_Min (A, B : Element) return Element;

function Bad_Min (A, B : Element) return Element is
begin
   if A < B then      -- এখানে error
      return A;
   else
      return B;
   end if;
end Bad_Min;

Element শুধু private বলে ঘোষিত, তাই < চলবেই এমন নয়। তুলনা করতে চাইলে চুক্তিতে যোগ করেন।

generic
   type Element is private;
   with function "<" (Left, Right : Element) return Boolean is <>;
function Generic_Min (A, B : Element) return Element;
private-এ তুলনা চলে নাFormal part-এ comparison না থাকলে body-তে compile error।Body-তে তুলনা ব্যবহার করতে চানformal part-এ comparison function লেখাInstantiation-এ তুলনাযোগ্যতা যাচাইশুধু privateGeneric body-তে compile error

15.2 is <> «যা খুশি auto-infer» নয়

is <> সুবিধাজনক, কিন্তু জাদু নয়। Instantiation-এর জায়গায় মানানসই operator বা subprogram দৃশ্যমান থাকতে হয়। নিজস্ব comparison আলাদা package-এ রাখলে যথাযথ with বা use করুন, অথবা named করে স্পষ্ট করে দেওয়াই নিরাপদ।

procedure Sort_By_Age is new Generic_Insertion_Sort
  (Item_Type  => Person,
   Index      => Positive,
   Item_Array => Person_Array,
   "<"        => Younger_Than);

15.3 Instance অনুযায়ী exception-ও আলাদা হয়

Generic package-এর specification-এ exception ঘোষণা করলে প্রতিটি instance-এ আলাদা exception হয়।

package Int_Stack   is new Generic_Stack (Integer, 5);
package Float_Stack is new Generic_Stack (Float, 3);

এক্ষেত্রে Int_Stack.Stack_OverflowFloat_Stack.Stack_Overflow আলাদা exception। সাধারণ exception হিসেবে ধরতে চাইলে generic-এর বাইরে exception সংজ্ঞায়িত করার ডিজাইনও ভাবা যায়।

Instance অনুযায়ী আলাদা exceptionInt_Stack ও Float_Stack-এর Stack_Overflow আলাদা exception।আলাদা exceptionGeneric_StackStack_Overflow ঘোষণাInt_Stack.Stack_OverflowFloat_Stack.Stack_Overflow

15.4 Code size বাড়তে পারে

Generic runtime-এ অতিরিক্ত indirection এড়াতে সাহায্য করে, অন্যদিকে প্রতিটি type-এ instance তৈরি হয় বলে instance বেশি হলে code size বাড়তে পারে।

C++ template ও Rust-এর monomorphization-এও এই trade-off দেখা যায়। উচ্চ নির্ভরযোগ্য, embedded, real-time-এর দিকের ডেভেলপমেন্টে runtime-এর অনিশ্চয়তা কমানোর বদলে বিল্ড-এর তৈরি হওয়া অংশের সাইজ সামলানো — এই চিন্তা আসে।

Instantiation ও কোড সাইজপ্রতিটি instance আলাদা কোড তৈরি করে সাইজ বাড়তে পারে।একটি generic bodyInteger সংস্করণFloat সংস্করণLong_Float সংস্করণMy_Type সংস্করণতৈরি কোডRuntime type পরীক্ষা বা boxing এড়ানো সহজInstance বেশি হলে সাইজ বৃদ্ধি খেয়াল রাখুন

15.5 limited private যেখানে ব্যবহার করা উচিত

type Element is private; assignment ধরে নেয়। File handle, lock, device handle — কপি হোক চান না এমন জিনিস সামলাতে limited private ভাবুন।

generic
   type Resource is limited private;
   with procedure Close (R : in out Resource);
procedure Generic_Use_And_Close (R : in out Resource);

কপি করা যায় না এমন type সামলানো ডিজাইনে মান রাখে এমন container-এর চেয়ে, procedure প্রয়োগ করা algorithm বা reference স্পষ্ট রাখা ডিজাইন নিরাপদ।

16. ছোট ডিজাইন প্যাটার্নের সংকলন

এখান থেকে বাস্তবে প্রায় ব্যবহার হওয়া রূপ সংক্ষেপে সাজানো।

16.1 তুলনাযোগ্য মানেই শুধু Min দেওয়া

generic
   type Element is private;
   with function "<" (Left, Right : Element) return Boolean is <>;
function Generic_Min (A, B : Element) return Element;

function Generic_Min (A, B : Element) return Element is
begin
   if A < B then
      return A;
   else
      return B;
   end if;
end Generic_Min;
তুলনাযোগ্য মানে MinComparison function থাকলেই Generic_Min ছোট মান ফেরায়।ElementComparison function লাগেGeneric_Minছোট মান ফেরানো

16.2 Threshold-কে value parameter করা

generic
   type Count_Type is range <>;
   Threshold : Count_Type;
function Generic_Is_Over (Value : Count_Type) return Boolean;

function Generic_Is_Over (Value : Count_Type) return Boolean is
begin
   return Value > Threshold;
end Generic_Is_Over;

Value parameter runtime-এর সেটিং নয়, instance-এর ধর্ম হিসেবে আটকে রাখতে চাওয়া মানে মানায়।

16.3 আউটপুট মাধ্যম inject করা

generic
   type Element is private;
   with procedure Put (Item : Element);
procedure Generic_Print_Twice (Item : Element);

procedure Generic_Print_Twice (Item : Element) is
begin
   Put (Item);
   Put (Item);
end Generic_Print_Twice;

এই রূপে standard output, log, test-এর buffer — আউটপুট গন্তব্য বদলানো যায়।

আউটপুট মাধ্যম inject করাPut-কে formal subprogram করে console, log, test buffer বদলানো।Generic_Print_TwicePut-কে formal subprogram হিসেবে নেওয়াConsole আউটপুটLog আউটপুটTest-এর buffer

16.4 Array-এর index type আটকে না রাখা

Ada-তে array-এর index typeও জরুরি type তথ্য। Positive ধরে না নিয়ে দরকারে index type-ও formal parameter করলে পুনর্ব্যবহার বাড়ে।

generic
   type Element is private;
   type Index is (<>);
   type Array_Type is array (Index range <>) of Element;
procedure Generic_Clear (Arr : in out Array_Type; Value : Element);

এই ডিজাইনে Positive index-এর array ছাড়াও enumeration index-এর array চলে।

Array index type আটকে না রাখাDiscrete Index-এ Positive, enumeration, নিজস্ব integer চলে।Index is discretePositive rangeDay enumerationState enumerationনিজস্ব integer type

17. Ada-র মতো API-এর চেকলিস্ট

Generic লেখার শেষে এই দৃষ্টিভঙ্গিতে ফিরে দেখলে পড়া সহজ হয়।

Generic API চেকলিস্টFormal parameter কমানো থেকে test instance পর্যন্ত সাতটি দৃষ্টিভঙ্গি।Generic ডিজাইন চেকFormal parameter ন্যূনতম কিদরকারি operation formal part-এ স্পষ্ট কিprivate / range / digits ইত্যাদি category ঠিক কিNamed association দিয়ে পড়া যায় এমন instantiation কিInstance অনুযায়ী অবস্থা ও exception মাথায় আছে কিCode size বৃদ্ধি সহ্য করা যায় কিTest-এর instance তৈরি আছে কি

বাক্যে গুছিয়ে এমন।

  • Body-তে ব্যবহার করা operation অবশ্যই formal parameter-এর চুক্তি হিসেবে দেখা যাক।
  • private-এ চললে private রাখুন। Arithmetic লাগলে range <> বা digits <> ব্যবহার করুন।
  • তুলনা, hash, আউটপুট, রূপান্তর — type অনুযায়ী বদলানো behavior formal subprogram করুন।
  • Size বা threshold instance-এর ধর্ম হলে value parameter করুন।
  • অবস্থা থাকলে generic package, না থাকলে generic subprogram আগে ভাবুন।
  • Instantiation-এ argument যত বেশি, named association তত ব্যবহার করুন।
  • Exception ও অভ্যন্তরীণ অবস্থা প্রতিটি instance-এ স্বাধীন — এই ধরে ডিজাইন করুন।

18. নমুনার সম্পূর্ণ কাঠামোর উদাহরণ

নিবন্ধের নমুনা ফাইলে ভাগ করলে এমন কাঠামো পড়া সহজ করে।

সম্পূর্ণ নমুনার ফাইল কাঠামোgenerics ও demos-এ spec/body ও demo ফাইল ভাগ।ada-generic-programmingsrcgenericsdemosgeneric_swap.adsgeneric_swap.adbgeneric_stack.adsgeneric_stack.adbgeneric_insertion_sort.adsgeneric_insertion_sort.adbgeneric_statistics.adsgeneric_statistics.adbgeneric_count_if.adsgeneric_count_if.adbgeneric_kv_store.adsgeneric_kv_store.adbswap_demo.adbstack_demo.adbsort_demo.adbstatistics_demo.adbcount_if_demo.adbkv_demo.adb

ছোট নিবন্ধের নমুনা হলে এক ফাইলে জড়িয়ে gnatchop করাও সুবিধাজনক, কিন্তু বাস্তব ও দীর্ঘ রক্ষণাবেক্ষণ ভাবলে specification .ads ও body .adb আলাদা রাখাই Ada-র মতো কাঠামো।

19. সারাংশ — type দিয়ে reuse-এর সীমানা ঠিক করা

Ada-র generic programming শুধু «type-এর উপর নির্ভর করে না এমন কোড লেখার ফিচার» নয়। আসল কথা, পুনর্ব্যবহারযোগ্য অংশ কী চায় তা type, subprogram ও value-এর চুক্তি হিসেবে স্পষ্ট করা

চুক্তি থেকে reuse পর্যন্তContract লেখা, body লেখা, instantiation, type-safe reuse।চুক্তি লেখাGeneric body লেখাType, value, function দিয়ে instantiateType-safe ব্যবহারকপি ছাড়া পুনর্ব্যবহার

এই নিবন্ধে দেখা গেছে, Ada generic-এ নিচের জিনিস formal parameter করা যায়।

  • Type
  • Value
  • Subprogram
  • Package

আর type-এর জন্য private, limited private, range <>, mod <>, digits <>, delta <>, (<>) — বেশ নির্দিষ্ট category দেওয়া যায়। এতে generic body «চলবে কি না জানা নেই এমন operation»-এর উপর নির্ভর করে না, চুক্তিতে লেখা operation দিয়েই নিরাপদে বাস্তবায়িত হয়।

C বা পুরোনো C++ সম্পদে reuse-এর জন্য macro, void*, function pointer, হাতে লেখা type শাখা ব্যবহার হয় কখনো। Ada-র generic সেই ব্যবহারের অনেকটা type-safe, পড়া যায় এমন রূপে বদলে দিতে পারে। বিশেষ করে দীর্ঘ রক্ষণাবেক্ষণ, embedded, real-time, উচ্চ নির্ভরযোগ্য সফটওয়্যারে «compile-time-এ সীমানা ঠিক করা ডিজাইন» বড় মূল্য রাখে।

20. সংশ্লিষ্ট পরামর্শের ক্ষেত্র

KomuraSoft LLC Windows অ্যাপ ডেভেলপমেন্ট, বিদ্যমান সম্পদ খতিয়ে দেখা ও সংশোধন, COM / ActiveX / 32bit / 64bit সীমানা গুছানো, প্রযুক্তি পরামর্শ ও ডিজাইন রিভিউ নিয়ে কাজ করে। Ada-র মতো statically typed, উচ্চ নির্ভরযোগ্যতার দিকের ডিজাইনই নয়, বিদ্যমান C/C++, C#, VB6, MFC, COM সম্পদ কীভাবে গুছিয়ে বাঁচিয়ে রাখা বা সরানো যায় — বাস্তবে সেটাও কাছাকাছি বিষয় হয়ে ওঠে।

তথ্যসূত্র

  • Ada 2022 Language Reference Manual, Section 12: Generic Units — generic unit-এর বিধান নিজেই। 12.1 generic ঘোষণা, 12.3 instantiation, 12.4 formal object (value parameter), 12.5 formal type (private, range <>, digits <> ইত্যাদি category), 12.6 formal subprogram, 12.7 formal package। এই নিবন্ধের কোনো অধ্যায়ে দ্বিধা হলে সংশ্লিষ্ট অনুচ্ছেদ খোলাই নিশ্চিত পথ।
  • Ada 2022 Language Reference Manual, 2.2: Lexical Elements, Separators, and Delimiters<>-কে compound delimiter «box» বলা হয় যেখানে সংজ্ঞায়িত। চিত্রের box লেখার ভিত্তি।
  • GNAT User’s Guide for Native Platformsgnatmake, gnatchop-এর ব্যবহার এবং -gnata সহ compile option-এর তালিকা। অধ্যায় ৩-এর ধাপে আটকে গেলে এখানে দেখুন।
  • Alire Documentationalr বসানো, toolchain (GNAT / gprbuild) ব্যবস্থাপনা, crate তৈরির পদ্ধতি আছে। শুধু পরিবেশ গড়তে এই নথিই যথেষ্ট।
  • নমুনা কোড (GitHub) — এই নিবন্ধের নমুনা অধ্যায় ১৮-এর কাঠামোয় ফাইলে ভাগ করা।

কাছাকাছি বিষয়ে গভীরে যেতে একই ট্যাগযুক্ত সাম্প্রতিক নিবন্ধ।

Ada দিয়ে রিয়েল-টাইম সিস্টেম প্রোগ্রামিং ── priority, period ও execution time নিয়ন্ত্রণ বাস্তবে

Ada-এর Annex D (রিয়েল-টাইম সিস্টেম) আটটি ব্যবহারিক কোড উদাহরণ দিয়ে শেখা যায়। টাস্ক priority, Ceiling_Locking, delay until দিয়ে period...

Windows ভার্চুয়ালাইজেশনের গভীরতা (পর্ব ৩) — সেকেন্ডে বুট হওয়া ভার্চুয়াল মেশিন: WSL2, Windows Sandbox ও কন্টেইনার এত হালকা কেন

WSL2 ও Windows Sandbox সেকেন্ডে শুরু হয়ে এত হালকা মনে হয় কেন? এই নিবন্ধ ডায়নামিক বেস ইমেজ ও ডাইরেক্ট ম্যাপ থেকে ডায়নামিক মেমরি বরাদ্দ...

Windows ভার্চুয়ালাইজেশনের গভীরতা (পর্ব ২) — কার্নেলও দেখতে পায় না এমন মেমরি: VBS, HVCI ও Credential Guard কীভাবে কাজ করে

সামঞ্জস্যপূর্ণ হার্ডওয়্যারে ক্লিন ইনস্টলে VBS ডিফল্টে চালু থাকে এবং হাইপারভাইজার ও SLAT দিয়ে কার্নেলের চেয়ে শক্তিশালী আইসোলেশন তৈরি কর...

Windows ভার্চুয়ালাইজেশনের গভীরতা (পর্ব ১) — আপনার Windows আসলে কোথায় চলছে? হাইপারভাইজার ও পার্টিশন

Hyper-V চালু করলে হোস্ট Windows নিজেই রুট পার্টিশন হিসেবে হাইপারভাইজারের উপর চলে। এই নিবন্ধ VT-x, SLAT ও VMBus-এর ভূমিকা দিয়ে ভার্চুয়াল...

এই পৃষ্ঠাগুলো বিষয়টিকে সেবা ও সিদ্ধান্তের বৃহত্তর প্রেক্ষাপটে স্থাপন করে।

প্রায়শ জিজ্ঞাসিত প্রশ্ন

এই নিবন্ধের বিষয়ে পরামর্শে প্রায়ই আসা প্রশ্ন।

Ada-র generic কী?
Type, value, subprogram, এমনকি package নিজেকেই formal parameter হিসেবে নেয়, আর new দিয়ে instantiation-এর মুহূর্তে statically type-check হয় — এমন এক reuse ব্যবস্থা। সাধারণ text substitution নয়, compile-time-এ «এই অংশ এই contract পূরণ করে কি না» স্থির করে। Generic subprogram শুধু declare করলেই ডাকা যায় না; নির্দিষ্ট type দিয়ে instantiate করলে তবেই সাধারণ procedure বা function হিসেবে ব্যবহার করা যায়।
Ada-র generic আর C++ template-এর ফারাক কী?
Ada শুরু থেকেই চুক্তি স্পষ্ট করে লেখা contract model ব্যবহার করে। Generic-এর body শুধু formal parameter যে operation-এর প্রতিশ্রুতি দিয়েছে সেগুলো দিয়ে লেখা হয়, আর body একাই type-check হয়। C++ template historically instantiation-এর আগে error দেখায় না; C++20-এর concepts সেটা উন্নত করেছে। Ada-তে value parameter ও subprogram parameter ছাড়াও package নিজেকে formal parameter করা যায়, তাই generic অংশগুলোকে একে অপরের সঙ্গে জোড়া যায়।
Ada-র formal type parameter-এ type category কেন নির্দিষ্ট করেন?
Body-তে যে operation ব্যবহার করা যাবে তা contract হিসেবে স্পষ্ট করতে। type T is private হলে assignment বা equality-র মতো মৌলিক operation ছাড়া আর কিছু ধরে নেওয়া যায় না; ছোট-বড় তুলনা বা arithmetic চলে না। Integer arithmetic লাগলে range <>, floating-point লাগলে digits <>, bitwise লাগলে mod <> — এভাবে category দেন। Category নির্দিষ্টকরণ পাঠককেও «এই অংশ কী চায়» বলে দেওয়া type-level specification হিসেবে কাজ করে।
Ada generic-এ কী কী খেয়াল রাখবেন?
প্রতিটি type-এর জন্য আলাদা instance তৈরি হয় বলে instance বেশি হলে code size বাড়তে পারে। C++ template ও Rust-এর monomorphization-এও এই trade-off দেখা যায়। Generic package-এর specification-এ ঘোষিত exception প্রতিটি instance-এ আলাদা exception হয়ে যায়। Formal parameter প্রথমে ন্যূনতম রাখুন, বদলাবার কারণ দেখা দিলে বাড়ান; argument বেশি হলে instantiation-এ named association ব্যবহার করুন — এগুলোই বাস্তব নির্দেশিকা।

লেখকের প্রোফাইল

নিবন্ধের লেখকের পরিচিতি পৃষ্ঠা।

Go Komura

KomuraSoft LLC-এর প্রতিনিধি

Windows সফটওয়্যার ডেভেলপমেন্ট, প্রযুক্তিগত পরামর্শ ও বাগ তদন্তে বিশেষজ্ঞ, বিশেষ করে বিদ্যমান সিস্টেমযুক্ত প্রকল্প ও পুনরুৎপাদন করা কঠিন বাগে।

পাবলিক লিঙ্ক

ব্লগে ফিরে যান