টাইপ সিস্টেম (Type System)

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

টাইপ (Type) বলতে মূলত বোঝায় একটা সেট অফ ভ্যালুস (set of values) এবং এই ভ্যালুগুলোর উপর Addition, Subtraction সহ কি কি অপারেশন কিভাবে করা যাবে তার নিয়মগুলি। যেমন বেশিরভাগ ল্যাঙ্গুয়েজে int টাইপ বলতে বোঝায় 32 বিটের signed number গুলিকে। যেগুলির মধ্যে addition, subtraction এই ধরনের অপারেশনগুলো সাধারণ Arithmetic Operation এর মতই কাজ করবে। আবার String বলতে বোঝায় অনেকগুলো character এর সমষ্টিকে, যেখানে “12” আর “34” দুইটি ভিন্ন স্ট্রিংকে + অপারেটর দিয়ে যোগ করলে সেটা “46” না হয়ে concatenate হয়ে “1234” হয়। একইরকম ভাবে আমরা যদি নিজেদের মত করে কোনো একটা Class বানিয়ে নেই, তাহলে সেটাও একটা Type হিসেবে কাজ করবে, যেটাতে ডাটার ধরন কেমন হবে, কি কি অপারেশন করা যাবে সেগুলো বলে দেয়া থাকবে।

এখন কোনো একটা টাইপের জন্য যেই অপারেশনগুলো বৈধ না তা করা হলে, অর্থাৎ দুইটা ভিন্ন টাইপের ডাটার মধ্যে কোনো একটা অপারেশন চালানো হলে যেটা কিনা ঐ টাইপগুলো কিভাবে হ্যান্ডেল করবে বুঝতে পারেনা, সেটার জন্য যা ঘটবে তা হলো টাইপ এরর (Type Error)। যেমন কোনো কোনো ল্যাঙ্গুয়েজে একটা স্ট্রিং আর একটা ইন্টিজারকে + অপারেটর দিয়ে যোগ করার চেষ্টা করলে সেটা Type Error দিবে। একইভাবে কোনো একটা অবজেক্টের ডেফিনিশনে যদি কোনো মেথড ডিফাইন করা না থাকে, কিন্তু সেই মেথডটা call করার চেষ্টা করা হয়, সেটাও একটা টাইপ এরর হবে। কোনক্ষেত্রে টাইপ এরর হবে এটা পুরোপুরি নির্ভর করে প্রোগ্রামিং ল্যাঙ্গুয়েজটা কিভাবে ডিজাইন করা হয়েছে তার উপরে। এটার কোনো ইউনিভার্সাল কমন রুল নেই।

এই যে প্রোগ্রামে টাইপ দেয়া না দেয়া, এবং এই সংক্রান্ত পুরো জিনিসটা টাইপ সিস্টেম (Type System) নামে পরিচিত। আর এই টাইপিং সিস্টেম নিয়ে কম্পিউটার বিজ্ঞানে একটা শাখাই আছে যার নাম টাইপ থিওরী (Type Theory)। আমরা আপাতত অত জটিল তত্ত্বকথায় যাবো না। আমাদের কাজ করার জন্য যতটুকু জানা প্রয়োজন শুধু ততটুকু নিয়েই আলোচনা করবো।

টাইপ সিস্টেম আসলে একটা সেট অব রুলস (set of rules) যেটা বলে দেয় যে, এই প্রোগ্রামিং ল্যাঙ্গুয়েজটা কিভাবে ভ্যালুগুলোর টাইপ নির্ধারণ করবে, টাইপ কি কম্পাইল টাইমে চেক হবে নাকি রানটাইমে, এক টাইপের ভ্যালু আরেক টাইপের ভ্যালুতে কতটুকু পর্যন্ত কনভার্সন করা যাবে বা আদৌ যাবে কিনা- এইসব।

শুরুতেই একটু বলে নেই। কম্পাইল টাইম আর রান-টাইমের পার্থক্য জানা আছে তো? আমরা যেই প্রোগ্রাম লিখি সেটা হলো মূলত Source Code, আর সেটা পরে কম্পিউটারের বোঝার মত করে Translate করে মেশিন কোডে রুপান্তর করে Compiler কিংবা Interpreter. এই ট্রান্সলেশনের সময়টাই হলো কম্পাইল টাইম।
রান টাইম বলতে বোঝায় ট্রান্সলেশনের পরে যখন কোডের ইন্সট্রাকশনগুলো সত্যিকারভাবে এক্সিকিউট হয় সে সময়টাকে।

স্ট্যাটিক টাইপ (Static Type):

স্ট্যাটিক টাইপড ল্যাংগুয়েজে প্রত্যেকটি ভ্যারিয়েবল বা অবজেক্টের আগে টাইপ ইনফরমেশন থাকতে হয়।

যেমনঃ

int val = 10;

এখানে আমরা আগে থেকেই বলে দিচ্ছি যে, ‘val’ একটা integer টাইপের ভ্যারিয়েবল এবং ইন্টিজার টাইপের ছাড়া অন্য কোনো টাইপের ডাটা যদি আমরা একে এসাইন করি তাহলে আমাদের কোড কম্পাইল করার সময়ই সেটা এরর দিবে। কারণ স্ট্যাটিক টাইপ ল্যাঙ্গুয়েজে সব ডাটার টাইপ কম্পাইল টাইমেই চেক করা হয়। কম্পাইলারের একটা পার্ট হচ্ছে টাইপ চেকার (Type Checker), যার একটা কাজ হচ্ছে প্রোগ্রামের টাইপগুলোর কোনো টাইপে যদি গড়মিল পাওয়া যায় তাহলে কোড কম্পাইল করতে বাধা দেয়া। অর্থাৎ প্রোগ্রাম এক্সিকিউশন বা রান হওয়ার আগেই স্ট্যাটিক টাইপ ল্যাঙ্গুয়েজে টাইপ চেকিং এর কাজ হয়ে যায়। মজার ব্যাপার হচ্ছে এই টাইপ চেকার কিন্তু কোনো একটা প্রোগ্রাম রান হলে যেই যেই টাইপের জন্য প্রব্লেম হবে সেগুলো খুঁজে খুঁজে আটকায় না, কারণ প্রোগ্রাম তো ততক্ষনে কম্পাইলই হয়নি, তাহলে রানটাইমের টাইপ চেক কিভাবে করবে? মূলত টাইপ চেকার বেশ ইন্টিলিজেন্টলি পুরো কোডের অপারেশনগুলোর উপর একটা ধারণা করে নেয় মাত্র। সেখান থেকে সে বলে কোন অপারেশনগুলোর জন্য ঝামেলা হতে পারে আর সেইগুলোর জন্য টাইপ এরর দেয়। যেহেতু আমাদের প্রোগ্রামে অনেক রকম কন্ডিশন আর ব্রাঞ্চিং (সহজভাবে বোঝার জন্য if else) থাকে, সেখানে এমন হতে পারে কোনো একটা কোডলাইন জীবনেও এক্সিকিউট হবে না, কিন্তু যেহেতু টাইপ চেকার ব্রাঞ্চিং বোঝে না, বা ব্রাঞ্চিং লজিক নিয়ে কাজ করার তার সুযোগ নেই, তাই সে ঐ লাইনে কোনো টাইপ এরর থাকলেও সেটার জন্য এরর দেবে। কম্পাইল টাইমের এরর আর রানটাইমের এরর এর পার্থক্য বোঝার জন্য এই ব্যাপারটা মাথায় রাখা জরুরী।

ডাইনামিক টাইপ (Dynamic Type):

ডাইনামিক টাইপে টাইপ নির্ভর করে ভ্যারিয়েবলটাতে কি ধরনের ডাটা এসাইন করা হয়েছে তার উপর। এই টাইপ সিস্টেমে সব ভ্যারিয়েবলকে একই রকম সাধারণ একটা বাকেটের মত মনে করা হয়। পরবর্তীতে এই ভ্যারিয়েবলে কি টাইপের ডাটা রাখা হচ্ছে বা অপারেশন করা হচ্ছে সেটার উপরই টাইপ নির্ধারণ হয়। যেমন পাইথনে যদি নীচের কোডটুকু দেখিঃ

val = "a"
print(val)
val = 10
print(val)

এখানে প্রথমে ‘val’ তে একটা স্ট্রিং এসাইন করা হয়েছে তারপর সেটা প্রিন্ট করা হয়েছে, আবার তারপরেই ‘val’ তে একটা integer এসাইন করে সেটা প্রিন্ট করা হয়েছে। এই কোডটা সঠিকভাবেই রান করবে। কারণ যেহেতু পাইথন একটা ডাইনামিক টাইপ ল্যাঙ্গুয়েজ তাই তাঁর ভ্যারিয়েবলগুলোর টাইপ কম্পাইল টাইমে চেক হয়না। সব ডাইনামিক টাইপ ল্যাঙ্গুয়েজের টাইপ চেক হয় রান টাইমে, অর্থাৎ প্রোগ্রাম যখন এক্সিকিউট বা রান হয় তখন প্রতিটা অপারেশন evaluate করে তার টাইপ নির্ধারণ করে নেয়া হয়। তাই পাইথন কম্পাইলার যখন দেখবে ‘val’ এ একটা স্ট্রিং এসাইন করা আছে, তখন সে সেটাকে একটা স্ট্রিং টাইপ ভ্যারিয়েবল মনে করবে, আবার যখন সেটায় একটা ইন্টিজার এসাইন করা হলো তখন সেটাকে একটা ইন্টিজার টাইপ হিসেবে ধরেই কাজ করবে।

জেনে রাখা ভালো যে বেশীরভাগ স্ক্রিপ্টিং ল্যাঙ্গুয়েজ (Scripting Language) যেমন python, ruby, javascript, php ডাইনামিক টাইপ ল্যাঙ্গুয়েজ।

স্ট্রংলি টাইপড (Strongly Typed), উইকলি টাইপড (Weakly Typed):

কোনটাকে স্ট্রংলি টাইপ বলা যাবে, কোনটাকে যাবে না সেটা নিয়ে বেশ দ্বিমত আছে। সাধারণভাবে বলা যায় যে, স্ট্রংলি টাইপড ল্যাঙ্গুয়েজে অনেক বেশী রেস্ট্রিকশন থাকে যাতে করে এক টাইপের ভ্যালু অন্য টাইপে এসাইন বা কনভার্ট করা না যায়। একটা উদাহরণ দিয়ে ব্যাপারটা পরিস্কার করিঃ

C তে আমরা জানি যে, আমরা এই রকম কোড লিখতে পারি-

char val = 10;

এখানে যদিও ‘val’ একটা ক্যারেক্টার টাইপের ভ্যারিয়েবল, কিন্তু তারপরেও আমরা সেটাতে একটা ইন্টিজার টাইপের ডাটা এসাইন করতে পারি। কম্পাইলার কোনো এরর দিবে না। কেন? কারণ, C আসলে সব কিছুকেই number হিসেবে চেনে। ক্যারেক্টার টাইপের ডাটাগুলোও C এর কাছে একটা নাম্বারই যেটাকে সে ASCII ভ্যালু দিয়ে হিসেব করে। একারণেই উপরের কোডটিকে C এর কম্পাইলার এরর মনে করবে না।
C কি তাহলে খুব কঠিনভাবে একটা ভ্যালুর টাইপের রেস্ট্রিকশন দিলো? না, দেয়নি। একারণেই C কে বলা হয় উইকলি টাইপড (Weakly Typed)। এছাড়াও C এর void* (Void pointer) কে যে কোনো টাইপের পয়েন্টারে কনভার্ট করা যায়, এক্ষেত্রে কম্পাইলার কোনো ধরনের রেস্ট্রিকশন দেয় না। এরকম বেশ কিছু কারণে C কে স্ট্রংলি টাইপড বলা যায় না। যদিও আপনি নেটে খুঁজলে অনেক জায়গায়ই হয়তো দেখবেন অনেকে C কেও Weakly Typed বলতে নারাজ। তাদের ভাষ্যমতে C যেহেতু এ ধরনের কিছু ব্যতিক্রম ছাড়া অনেকাংশেই টাইপের ব্যাপারে রেস্ট্রিকশন দেয় সে হিসেবে C ও Strongly Typed Language.

যেহেতু, একটা ল্যাঙ্গুয়েজ ঠিক কতটুকু Weak হলে তাকে Weakly Typed বলা যাবে, বা কতটুকু রেস্ট্রিক্টেড হলে তাকে Strongly Typed বলা যাবে, এগুলি নিয়ে প্রচুর মতপার্থক্য আছে, তাই কোনো একটা ল্যাঙ্গুয়েজকে হুট করে Strong বা Weak Typed বলা যাবে না। সব চাইতে ভালো যেই বুদ্ধি গুরুজনরা দেন তা হলো,

“ল্যাঙ্গুয়েজগুলো কে Strong/Weak এ ভাগ না করাই উত্তম।”

উপরের বিষয়গুলো যদি মোটামুটি আইডিয়া হয়ে যায় তাহলে এর সাথে আরেকটা বিষয় খেয়াল করা খুব গুরুত্বপূর্ণ। তা হলো, Static/Dynamic এবং Weak/Strong একটার উপর আরেকটা নির্ভরশীল না। মানে হলো Static মানেই Strong না, কিংবা Dynamic মানেই Weak না। যেমনঃ আমরা যদি দেখি যে, C তে আমরা ভ্যারিয়েবলগুলোর টাইপ আগেই বলে দিচ্ছি এবং C টাইপের জন্য স্ট্রং রেস্ট্রিকশন দেয় না। সুতরাং C একটা Weak Static Typed Language.

আবার যেহেতু, Java অনেকাংশেই টাইপের জন্য স্ট্রং রেস্ট্রিকশন দেয় সেকারণে Java কে Strong Static Typed Language বলা যায়।

একইভাবে, আমরা যদি Python এ দেখি, নীচের কোডটুকু পাইথনে টাইপ এরর দিবে-

val = ‘str’ + 5

কিন্তু একইরকম কোড PHP তে ঠিকমতই কাজ করবে, কোনো এরর দিবে না (যদিও আউটপুট হয়তো আপনি যা এক্সপেক্ট করছেন তা হবে না) –

$val = ‘str’ + 5

এর কারণ হচ্ছে, PHP ল্যাঙ্গুয়েজ Weakly Typed এবং PHP এর ইন্টারপ্রেটার এই এক্সপ্রেশনের টাইপ এটার কাজের ধরন দেখে নিজের মত করে ধারণা করে নিচ্ছে। এই ব্যাপারটাকে বলা হয় implicit type conversion বা Coercion. যাই হোক একারণেই PHP হচ্ছে Weak Dynamic Typed Language আর Python হচ্ছে Strong Dynamic Typed Language.

গ্র্যাজুয়াল টাইপিং (Gradual Typing):

কোনো কোনো ল্যাঙ্গুয়েজে কিছু ভ্যারিয়েবলের টাইপ নির্ধারণ করে দেয়া যায়, যাতে করে সেগুলো কম্পাইল টাইমে চেক হয়, আবার একই সাথে কিছু ভ্যারিয়েবলের টাইপ উহ্য রাখা হয় যেগুলো রানটাইমে চেক হবে। এই ধরনের টাইপ সিস্টেমকে বলা হয় গ্র্যাজুয়াল টাইপিং (Gradual Typing)। সাধারণত ডাইনামিক টাইপড ল্যাঙ্গুয়েজগুলোকে কিছুটা ইমপ্রুভ করে তাতে স্ট্যাটিক টাইপ চেকিং এর কিছু সুবিধা যুক্ত করে এই কাজ করা হয়। Javascript এর TypeScript, PHP এর Hack, Python এর Cython — এই সবগুলোতে গ্রাজুয়াল টাইপিং সুবিধা আছে।

এই আর্টিকেলটায় গ্রাজুয়াল টাইপিং খুবই সুন্দর করে ব্যাখ্যা করা হয়েছে।

সুবিধা, অসুবিধাঃ

স্ট্যাটিক টাইপ সিস্টেম ভাল কারণ এটি আপনাকে ঝামেলা থেকে দূরে রাখবে। কম্পাইলার কম্পাইল করার সময় সব ধরণের বৈধতা যাচাই করে, এবং আপনি একটি ভ্যারিয়বলে ভুল টাইপ নির্ধারণ করার চেষ্টা করলেই আপনাকে সাথে সাথে জানিয়ে দেবে। যেহেতু রানটাইমে কোডের টাইপ চেক করা লাগে না, তাই স্ট্যাটিক টাইপ কোড ডাইনামিক টাইপ কোডের চেয়ে সাধারণত faster হয়।

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

আশা করি টাইপ সিস্টেম সম্পর্কে কিছুটা হলেও আইডিয়া করতে পেরেছেন এতক্ষনে। আর না করতে পারলেও ভয় পাওয়ার কিছু নেই। কারণ বিখ্যাত বই ‘Types and Programming Languages’ এর লেখক Benjamin C. Pierce নিজেই বলেছেন-

I spent a few weeks… trying to sort out the terminology of “strongly typed,” “statically typed,” “safe,” etc., and found it amazingly difficult…. The usage of these terms is so various as to render them almost useless.

যাই হোক, এরপরেও আরো ভালো করে জানার আগ্রহ থাকলে নীচের লিঙ্কগুলোয় একটু ঢুঁ মেরে আসতে পারেন।

Type_system (Wikipedia)

Static/Dynamic vs Strong/Weak

Is C# a strongly typed or a weakly typed language?

what-to-know-before-debating-type-systems

what is gradual typing

--

--