হয়তো আপনি ফাংশনাল প্রোগ্রামিং সম্পর্কে শুনেছেন এবং কিছু প্রশ্ন আছে।
যেমন...
- ফাংশনাল প্রোগ্রামিং সঠিকভাবে কী?
- এটি অবজেক্ট-অরিয়েন্টেড প্রোগ্রামিং-এর সাথে কীভাবে তুলনা করা যায়?
- কি আপনাকে রুবিতে ফাংশনাল প্রোগ্রামিং ব্যবহার করা উচিত?
আমি এই প্রশ্নগুলোর উত্তর দিই যাতে আপনি একে কীভাবে কাজ করে সেটি সম্পর্কে একটি ভালো ধারণা পান।
ফাংশনাল প্রোগ্রামিং কী?
এটি শুধু একটি ফ্যাড বা ফ্যান্সি শব্দ নয়, এটি একটি আসল প্রোগ্রামিং প্যারাডাইম যা অনেক দিন ধরে আছে কিন্তু gầnামারই এটিকে পুনরুদ্ধার করেছে জনপ্রিয়তা।
এবং এই প্যারাডাইমের পেছনের বেসিক আইডিয়াগুলো আপনি যা মনে করছেন চেয়ে সহজ।
ফাংশনাল প্রোগ্রামিং-এ আমরা স্টেট পরিবর্তন এড়াই এবং "পিউর" ফাংশন লিখতে চাই।
স্টেট পরিবর্তন এড়ানো মানে এই ফাংশনগুলো ফাংশনের বাইরে কিছুই পরিবর্তন করে না, কোনো ইনস্ট্যান্স ভেরিয়েবল নেই, পাস করা কোনো অবজেক্ট পরিবর্তন করা নেই...
এমন কিছুই নেই!
একটি ফাংশনাল প্রোগ্রামিং ল্যাঙ্গুয়েজে (যেমন হ্যাসকেল) সকল ডেটা IMMUTABLE।
ভেরিয়েবল কিনतु আছে, কিন্তু সেগুলো গণিতের জগতের মতো আচরণ করে। একবার একটি ভেরিয়েবলকে একটি ভ্যালু দেয়া হলে, কম্পাইলার আপনাকে অন্য ভ্যালু দিয়ে এই ভেরিয়েবলকে রিডিফাইন করতে দেবে না।

ফাংশনাল প্রোগ্রামিং-এর সুবিধা
ইমমিউটাবিলিটি হলো ফাংশনাল প্রোগ্রামিং-এর প্রধান সুবিধা কারণ মিউটেবল ডেটা সূক্ষ্ম এররروز লিড করতে পারে যা ট্র্যাক করা কঠিন।
উদাহরণ:
def all_different_from_first?(arr)
first = arr.shift
arr.all? { |n| n != first }
end
arr = [1,3,5,7,9]
p all_different_from_first?(arr) # true
এই উদাহরণে আমি জানতে চাই অ্যারে-এর সব এলিমেন্ট প্রথম এলিমেন্ট থেকে ভিন্ন কিনা।
এটি কাজ করার জন্য আমাদের প্রথম এলিমেন্টটি অ্যারেতে থেকে রিমুভ করতে হবে এবং একই সাথে এই এলিমেন্টটি সংরক্ষণ করতে হবে যাতে আমরা বাকিগুলোর সাথে তুলনা করতে পারি।
আমরা এটা কীভাবে করব?
আমরা একটি অ্যারে নিয়ে কাজ করছি এবং আপনি উপলব্ধ মেথডগুলোর তালিকা দেখলে পাবেন Array#shift মেথডটি ঠিক আমাদের যা চাই সেটি করে।
এটি খুব ভালো কাজ করে যতক্ষণ না...
...আপনি arr-এর ভ্যালু দেখেন মেথড একবার কল করার পর:
all_different_from_first?(arr) # true arr # [3,5,7,9]
আশ্চর্য!
অ্যারেটি একটি এলিমেন্ট হারিয়ে গিয়েছে (1) এবং আমরা এটিকে লক্ষ্য করিনি।
এটিই এই ধরনের মিউটেবিলিটি বাগগুলো কতটা চমকাদার হতে পারে।
ঠিক করা ভার্সন:
def all_different_from_first?(arr)
arr[1..-1].all? { |n| n != arr.first }
end
ফাংশনাল বনাম OOP
কি আমরা সবাই ফাংশনাল প্রোগ্রামিং अपना নেব?
এটি মনে হতে পারে এই সব ইমমিউটেবল স্টেট ফাংশনাল প্রোগ্রামিংকে OOP-এর সম্পূর্ণ বিপরীত করে দিয়েছে, এবং একটু সेंসে এটি সত্য, কিন্তু এখনও একটি উপায় আছে যাতে দুটি প্রোগ্রামিং প্যারাডাইম একসাথে কাজ করতে পারে।
তাই না, ফুল-অন ফাংশনাল প্রোগ্রামিংয়ে যাওয়ার কোনো দরকার নেই। রুবি OOP-এর জন্য ডিজাইন করা, তাই আপনি ধানের বালি বিপরীত দিয়ে লড়াই করবেন।
ভালো খবর:
আপনি এখনও ফাংশনাল প্রোগ্রামিং-এর সেরা আইডিয়াগুলো ব্যবহার করতে পারেন এবং আপনার রুবি কোডে প্রয়োগ করতে পারেন।
আসুন কথা বলি কীভাবে করতে হবে।
যে Architekten সম্ভব মিউটেবিলিটি কমানো
এটি করার একটি উপায় হলো attr_accessor ব্যবহার করা বন্ধ করুন, শুধু attr_reader-এ টিকে থাকুন।
এটি করার পর আপনাকে স্ট্রিং, অ্যারে এবং হ্যাশের ওপর নজর রাখতে হবে।
এই অবজেক্টগুলোকে পরিবর্তন করার মেথড আছে:
- বেশিরভাগ মেথড যাদের শেষে
!থাকে (যেমনgsub!) - delete
- update
- clear
- shift / unshift / pop / push
প্রথম ধাপ হলো এই মেথডগুলোর সচেতন হওয়া।
আপনি যদি এই মেথডগুলোর যেকোনো একটি ব্যবহার করতে হয় তবে আপনি একটি ডুপ্লিকেট অবজেক্টের ওপর কাজ করতে পারেন।
একটি স্ট্রিং এবং সেটির একটি ক্লোন দিয়ে:
str = "abcd" dup = str.dup
আমরা ডুপ্লিকেট স্ট্রিংটি clear করলে এই ফলাফল পাই:
dup.clear # str => "abcd" # dup => ""
এটি মূল স্ট্রিংকে সুরক্ষিত রাখে।
পারশিয়াল অ্যাপ্লিকেশন
ফাংশনাল প্রোগ্রামিং-এ ইমমিউটেবল ডেটা এবং পিউর ফাংশন ছাড়াও আরও কিছু আছে।
যেমন ফাংশনların পারশিয়াল অ্যাপ্লিকেশন, যাকে "কারিয়িং" ও বলা হয়।
উদাহরণ:
def add(a,b) a + b end add_five = method(:add).curry[5] add_five.call(5) # 10 add_five.call(20) # 25
লক্ষ্য করুন কীভাবে add মেথড দুটি আর্গুমেন্ট নেয়, কিন্তু curry মেথড ব্যবহার করে আমরা আর্গুমেন্টের একটি "প്രീলোড" করতে পারি।
তারপর আমরা একটি ল্যাম্বডা পাই যা শুধু ২য় আর্গুমেন্ট দিয়ে কল করা যায়।
আরেকটি উদাহরণ:
list = (1..10)
greater_than = ->(x,y) { y > x }.curry
list.select(&greater_than.(5)) # [6, 7, 8, 9, 10]
list.select(&greater_than.(8)) # [9, 10]
আরেকটি উদাহরণ:
divisible_by = ->(x,y) { y % x == 0 }.curry
list.select(&divisible_by.(5)) # [5, 10]
list.select(&divisible_by.(2)) # [2, 4, 6, 8, 10]
সারসংক্ষেপ
আপনি ফাংশনাল প্রোগ্রামিং সম্পর্কে শিখতে পেরেছেন, এর কোর হলো পিউর ফাংশন এবং ইমমিউটেবল ডেটা, এটি শুধু আপনার কোড সম্পর্কে চিন্তা করার একটি উপায় এবং OOP-এর সাথে সম্পূর্ণ অসঙ্গতিপূর্ণ নয়।
পড়ার জন্য ধন্যবাদ, নিউজলেটার সাবস্ক্রাইব করা ভুলবেন না যদি এখনো না করে থাকেন! 🙂