মৌলিক অ্যারে অপারেশন ইমপ্লিমেন্ট করুন।
ফাংশনাল ভাষায় length, map, ও reduce-এর মতো অ্যারে অপারেশন খুবই কমন। বিদ্যমান ফাংশন ব্যবহার না করেই একগুচ্ছ মৌলিক অ্যারে অপারেশন ইমপ্লিমেন্ট করুন।
বিদ্যমান নামের সঙ্গে সংঘর্ষ এড়াতে যে অপারেশনগুলো ইমপ্লিমেন্ট করা হবে তার সঠিক সংখ্যা ও নাম track-এর উপর নির্ভর করবে, তবে আপনি যে সাধারণ অপারেশনগুলো ইমপ্লিমেন্ট করবেন সেগুলো হলো:
append (দুটি অ্যারে দেওয়া হলে, দ্বিতীয় অ্যারের সব এলিমেন্ট প্রথম অ্যারের শেষে যোগ করুন);concatenate (একগুচ্ছ অ্যারে দেওয়া হলে, সব অ্যারের সব এলিমেন্ট একত্র করে একটি সমতল অ্যারে বানান);filter (একটি প্রেডিকেট ও একটি অ্যারে দেওয়া হলে, যেসব এলিমেন্টের জন্য predicate(item) ট্রু হয় সেসব এলিমেন্টের অ্যারে রিটার্ন করুন);length (একটি অ্যারে দেওয়া হলে, তার ভেতরে থাকা এলিমেন্টের মোট সংখ্যা রিটার্ন করুন);map (একটি ফাংশন ও একটি অ্যারে দেওয়া হলে, সব এলিমেন্টে function(item) প্রয়োগ করার ফলাফলগুলোর অ্যারে রিটার্ন করুন);foldl (একটি ফাংশন, একটি অ্যারে এবং একটি প্রাথমিক অ্যাকুমুলেটর দেওয়া হলে, বাম দিক থেকে প্রতিটি এলিমেন্ট অ্যাকুমুলেটরে ফোল্ড (রিডিউস) করুন);foldr (একটি ফাংশন, একটি অ্যারে এবং একটি প্রাথমিক অ্যাকুমুলেটর দেওয়া হলে, ডান দিক থেকে প্রতিটি এলিমেন্ট অ্যাকুমুলেটরে ফোল্ড (রিডিউস) করুন);reverse (একটি অ্যারে দেওয়া হলে, মূল সব এলিমেন্ট নিয়ে একটি অ্যারে রিটার্ন করুন, তবে উল্টো ক্রমে)।লক্ষ্য করুন, ফোল্ড ফাংশনগুলোতে (foldl, foldr) আর্গুমেন্ট যে ক্রমে পাঠানো হয় সেটি গুরুত্বপূর্ণ।
এই অনুশীলনীর জন্য আপনাকে Odin-এর প্যারামিটার পলিমরফিজম (যা বেশি প্রচলিতভাবে জেনারিক নামে পরিচিত) ব্যবহার করতে হবে। আপনি যদি আগে এই ফিচারটি না দেখে থাকেন, তাহলে শুরু করার জন্য এখানে একটি সংক্ষিপ্ত পরিচিতি দেওয়া হলো।
প্যারামিটার পলিমরফিজম হলো প্রোগ্রামিং ভাষার একটি ফিচার, যা প্রোগ্রামারদের নিজেদের কোডে ব্যবহৃত টাইপ সম্পর্কে কম নির্দিষ্ট (অর্থাৎ আরও জেনারিক, নামটি এসেছে এখান থেকেই) থাকার সুযোগ দেয়, আর একই সঙ্গে টাইপ সেফটিও বজায় থাকে। স্পষ্টতই, এটি কেবল Odin-এর মতো স্ট্রংলি-টাইপড ভাষার ক্ষেত্রেই অর্থবহ।
চলুন একটি উদাহরণ দিয়ে শুরু করি। ধরা যাক, আপনি একটি অ্যারের সব এলিমেন্ট একটি নির্দিষ্ট মান দিয়ে ইনক্রিমেন্ট করতে চান, যা মোটামুটি সহজ একটি সমস্যা।
incr_array_int :: proc(a: []int, by: int) -> []int {
new_array := make([]int, len(a))
for i := 0; i < len(a); i+= 1 {
new_array[i] = a[i] + by
}
return new_array
}
এখন যদি ফ্লোটিং পয়েন্টের জন্যও একই কার্যকারিতা দরকার হয়?
incr_array_f64 :: proc(a: []f64, by: f64) -> []f64 {
new_array := make([]f64, len(a))
for i := 0; i < len(a); i+= 1 {
new_array[i] = a[i] + by
}
return new_array
}
আর তারপর আনসাইনড ইন্টিজার, ৩২-বিট ফ্লোট, এই জাতীয় সবকিছুর জন্যও?
অল্প সময়ের মধ্যেই আপনার কাছে একেবারে একই কাজ করে কিন্তু ভিন্ন টাইপে কাজ করা অসংখ্য প্রসিডিউর জমে যাবে। কোনো সময় লজিক আপডেট করার দরকার হলে আপনাকে সেটি সব ভ্যারিয়েন্টের জন্যই করতে হবে, যা অনেক মেইনটেন্যান্স কাজে পরিণত হতে পারে। আরেকটি ঝামেলা হলো, প্রতিটি প্রসিডিউরকে আলাদা নাম দিতে হয়, কারণ Odin ইমপ্লিসিট প্রসিডিউর ওভারলোডিং সমর্থন করে না (এক্সপ্লিসিট ওভারলোডিং অবশ্য ব্যবহার করা যায়, তবে সেটি অন্য অনুশীলনীর গল্প)।
Odin একটি বাস্তবধর্মী ভাষা হওয়ায় প্যারামিটার পলিমরফিজমের মাধ্যমে একটি সমাধান দেয়।
কম্পাইলার যতক্ষণ কম্পাইল টাইমে একটি প্যারামিটারের টাইপ বের করতে পারে, ততক্ষণ আপনি সেটিকে T-এর মতো একটি জেনারিক নাম দিতে পারেন।
চলুন উপরের প্রসিডিউরটি আবার লিখি:
incr_array :: proc(a: []$T, by: T) -> []T {
new_array := make([]T, len(a))
for i := 0; i < len(a); i+= 1 {
new_array[i] = a[i] + by
}
return new_array
}
লক্ষ্য করুন, আমরা সব টাইপ অ্যানোটেশন (int বা f64) T দিয়ে বদলে দিয়েছি এবং T-এর প্রথম উপস্থিতির আগে একটি ডলার চিহ্ন ($T) বসিয়েছি।
$T টাইপটি Odin কম্পাইলারকে জানায় যে T নামটি টাইপের একটি জেনারিক নাম, যা কম্পাইলের সময় প্রকৃত নাম দিয়ে প্রতিস্থাপিত হবে।
আর কম্পাইলার এখন যেহেতু জেনারিক টাইপ T সম্পর্কে জানে, তাই একই টাইপের পরের উপস্থিতিগুলো কেবল নির্বাচিত টাইপ নাম (T) দিয়ে চিহ্নিত করলেই হয়।
এখন আপনি এ রকম কোড লিখতে পারেন:
a_int := incr_array([]int{1, 2, 3}, 10)
a_f64 := incr_array([]f64{1.0, 2.0, 3.0}, 10.0)
প্রথম স্টেটমেন্টে Odin কম্পাইলার প্রথম প্যারামিটারের টাইপ ([]int) জেনারিক প্যারামিটারের টাইপ ([]$T) হিসেবে শনাক্ত করবে, সিদ্ধান্তে পৌঁছাবে যে T = int, এবং তারপর T-এর সব পরবর্তী উপস্থিতি int দিয়ে প্রতিস্থাপিত করে একটি সংস্করণ কম্পাইল করবে (যা উপরের বিশেষায়িত সংস্করণ incr_array_int()-এর সমতুল্য)।
আপনি যদি প্রথম প্যারামিটারের সংজ্ঞায় ডলার চিহ্নটি বাদ দিতেন, তাহলে কম্পাইলার বর্তমান প্যাকেজে এবং ইমপোর্টের তালিকায় T নামের একটি টাইপ খুঁজত এবং সম্ভবত একটি কম্পাইলেশন এরর ফিরিয়ে দিত Error: Undeclared name: T।
দ্বিতীয় স্টেটমেন্টটি প্রথমটির মতোই কাজ করে, তবে সেখানে কম্পাইলার T-কে f64 হিসেবে শনাক্ত করে।
জেনারিক টাইপের নাম এক অক্ষরের রাখা রীতি (T ও E প্রায়ই ব্যবহৃত হয়)
প্যারামিটার পলিমরফিজম, অর্থাৎ জেনারিক টাইপ সম্পর্কে এখন আপনার কাছে List Operations অনুশীলনীটি করার মতো যথেষ্ট জ্ঞান থাকা উচিত।
Exercism-এ সাইন আপ করুন, Odin ট্র্যাকের 73টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।
রিকারশনের একটি ব্যবহারিক পরিচিতি উপভোগ করুন, অ্যারে অপারেশনের ইম্পারেটিভ ও ফাংশনাল বিকল্পগুলো ঘেঁটে দেখুন, আর টেল-কল রিকারশন ও অ্যাকুমুলেটর ফাংশনের গভীরে ডুব দিন।