Sunday, February 19, 2017

ফাংশনাল প্রোগ্রামিং কী (What is functional programming)

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

১৯৯০ সালে জন হাগেস (John Hughes) একটি আর্টিকেল প্রকাশ করেন যার বাংলা করলে এমনটা দাড়ায়- 

ফাংশনাল প্রোগ্রামিংয়ে কোনো অ্যাসইনমেন্ট স্টেটমেন্ট নেই। এর অর্থ হলো কোনো ভ্যারিয়েবলে একটি ভ্যালু অ্যাসাইন করা হলে তা আর পরিবর্তন হতে পারে না। অর্থাৎ ফাংশনাল প্রোগ্রামিংয়ে কোন সাইড ইফেক্ট (side effect) নেই। একটি ফাংশন কল শুধুমাত্র কিছু কম্পিউট করবে, কিন্তু এর অন্য কোনো সাইড ইফেক্ট থাকবে না। এতে করে অনেকগুলো প্রোগ্রামিং বাগ থেকে মুক্তি পাওয়া যায়। যেহেতু ফাংশন কলে কোনো সাইড ইফেক্ট নেই, তাই ফাংশন এক্সিকিউশনের ক্রম (আগে না পরে এক্সিকিউট হবে) অপ্রাসঙ্গিক হয়ে যায়- এবং তাই স্টেটমেন্টের ভ্যালু পরিবর্তন হওয়ার কোনো সম্ভবনা নেই। এতে করে কোনো স্টেটমেন্ট যেকোনো সময় ইভ্যালুয়েট করা যায় এবং প্রোগ্রমারকে প্রোগ্রামের নিয়ন্ত্রণ প্রবাহ(flow of control) (অর্থাৎ কোনটিকে আগে আর কোনটিকে পরে কল করতে হবে) থেকে মুক্তি দেয়। যেহেতু এক্সপ্রেশন যে কোনো সময় ইভ্যালুয়েট করা যায়, ফলস্বরূপ ফাংশনকে সহজে ভ্যালু দিয়ে প্রতিস্থাপন করা এবং ভ্যালুকে ফাংশন দিয়ে প্রতিস্থাপন করা যায় যা প্রোগ্রামে রেফারেন্সিয়াল ট্রান্সপারেন্সি (referential transparency) এনে দেয়। এই স্বাধীনতাটুকু প্রোগ্রামকে গাণিতিকভাবে টেস্ট করা সহজ করে দেয়। 

উপরের সংজ্ঞাতে কয়েকটি পরিভাষা(term) ব্যবহার করা হয়েছে। এগুলো এবার একটু দেখে নেওয়া যাক -

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

এই সাইড ইফেক্ট না থাকার অনেকগুলো অর্থ হয়। কোনো ফাংশন কলের ফলে নিচের কাজগুলো হবে না -
১. কোনো ভ্যারিয়েবল পরিবর্তন হবে না।
২. কনসোল বা স্ক্রিনে কোনো কিছু প্রিন্ট হবে না।
৩. ডাটাবেইজ, নেটওয়ার্ক বা অন্যকোনো ডিভাইসে ডেটা রাইট হবে না।
৪. কোনোরকম এক্সেপশন থ্রু করবে না।
ইত্যাদি

রেফারেন্সিয়াল ট্রান্সপারেন্সি :
কোনো একটি ফাংশনকে রেফরেন্সিয়ালী ট্রান্সপারেন্ট বলা যাবে যখন এটি সবসময় একই রকম ইনপুটের জন্য একই ফলাফল কম্পিউট করবে। 

double random = Math.random(); //Take #1 
double pow = Math.pow(2, 2);//Take #2

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

রেফারেন্সিয়াল ট্রান্সপারেন্ট ফাংশনের আরও বেশ কয়েকটি বেশিষ্ট্য হলো -

১. ফাংশনগুলো সবসময় স্বয়ংসম্পূর্ণ। এগুলো কোনো বিশেষ অবস্থার উপর নির্ভর করে না। এগুলোকে যেকোনো অবস্থান থেকে কল করা যাবে। এদেরকে কল করা জন্যে সঠিক আর্গুমেন্টই যথেষ্ট্য।
২. এগুলো একইরকম আর্গুমেন্টের জন্য সবসময় একইরকম ফলাফল প্রকাশ করবে। হঠাৎকরে আশ্চর্য হওয়ার কোনো সম্ভবনা নেই।
৩. এগুলো কখনো এক্সেপশন থ্রো করবে না। এগুলো এরর যেমন – OutOfMemoryError, StackOverflowError
ইত্যাদি দিতে পারে কিন্তু এক্সেপশন নয়। মেমোরির অভাবে প্রোগ্রাম ক্র্যাশ করতেই পারে, তবে এটি একটি রেফারন্সিয়াল ট্রান্সপারেন্ট ফাংশনের জন্য হয় না। এটি অন্যরকম সসম্যা।
৪. এই ফাংশনগুলো কোনোভাবেই এমন কোন পরিস্থিতি তৈরি করবে না যাতে করে অন্য কোনোকিছুর পরিবর্তন না সমস্যা তৈরি হয়। একটি ফাংশন কলের জন্যে কোডের অন্য অংশ ভেঙে যাবে না।
৫. এই ফাংশনগুলো বাইরের কোনো কিছুর অভাবে( যেমন- ফাইল অ্যাকেস, ইন্টারনেট কানেকশন, ডেটাবেইজ কানেকশন ইত্যাদি) বন্ধ হয়ে যাবে না। 

ফাংশনাল প্রোগ্রামিংয়ে এই দুটি বৈশিষ্ট্য ছাড়াও আরও বেশ কতগুলো বৈশিষ্ট্য রয়েছে সেগুলো হলো -

১. প্রথম শ্রেণির (First class) ফাংশন 
২. নামবিহীন (Annonymous) ফাংশন
৩. ক্লোজারস (Closures) 
৪. কারিং (currying)
৫. প্যারামেট্রিক পলিমরফিজম (parametric polymorphism)
৬. বীজগাণিতিক (algebraic) ডাটা টাইপ 
৭. লেজি এভালুয়েশন (Lazy evaluation)

এগুলো নিয়ে পরবর্তীতে আরো বিশদভাবে আলোচনা করা হবে। 

এবার ফাংশনাল প্রোগ্রামিংয়ের কতগুলো সুবিধা নিয়ে আলোচনা করা যাক -

১. যেহেতু একটি ফাংশন একইরকম আর্গুমেন্টের জন্যে একই ফলাফল দেয়, তাই টেস্ট করা সহজ হয়ে যায়। এতে ব্যপকভাবে টেস্ট করে অদ্ভুত সমস্য খুঁজে বের করতে হয় না। 
২. টেস্ট করা সহজ। যেহেতু কোনো সাইড ইফেক্ট নেই, তাই আলাদাকরে মক(Mock) করতে হয় না। যেকোনো ফাংশন এমনিতেই পৃথক। 
৩. সহজে মডুউলার প্রোগ্রাম লেখা যায় কারণ এগুলো শুধু ইনপুট এবং আউটপুট থেকে তৈরি। সাইড ইফেক্ট না থাকার কারণে কোনো ফাংশন কলের ফলে অন্য কোথাও কোনো সমস্যা হতে পারে কিনা তা নিয়ে চিন্তা করতে হয় না, এক্সেপশন থ্রো না করায় ক্যাচ করার প্রশ্ন আসে না, শেয়ার্ড ডেটা না থাকায় থ্রেড সেইফটি নিয়ে চিন্তা করতে হয় না। 
৪. একটি ফাংশনাল প্রোগ্রাম লেখার জন্যে কতগুলো বেইজ ফাংশন থেকে শুরু করতে হয়। সেগুলো কম্মবাইন করে আরও হায়ার লেভেল ফাংশন লিখতে হয়, এভাবে প্রক্রিয়াটি পুনঃব্যবহারের মাধ্যমে একটি ফাংশনে নিয়ে আসতে হয় যা দিয়ে পুরো প্রোগ্রামের কাজটি করা যায়। যেহেতু ফাংশনগুলো রেফারেন্সিয়ালি ট্রান্সপারেন্ট, তাই ফাংশনগুলো কোনো পরিবর্তন না করে অন্য জায়গায় ব্যবহার করা যায়।