স্ট্রাক্ট হলো ম্যাপের উপরে তৈরি একটি এক্সটেনশন, যা কম্পাইল-টাইম চেক আর ডিফল্ট মান দেয়। স্ট্রাক্টের নামকরণ করা হয় যে মডিউলে এটি ডিফাইন করা হয় সেই মডিউলের নাম অনুসারে। স্ট্রাক্ট ডিফাইন করতে defstruct কনস্ট্রাক্ট ব্যবহার করুন। সাধারণত এই কনস্ট্রাক্টটি মডিউল ডেফিনিশনের ঠিক পরেই বসে। defstruct হয় অ্যাটমের একটি লিস্ট নেয় (nil ডিফল্ট মানের জন্য), নাহয় একটি কিওয়ার্ড লিস্ট নেয় (নির্দিষ্ট ডিফল্ট মানের জন্য)। যে ফিল্ডগুলোর ডিফল্ট মান নেই সেগুলো অবশ্যই ডিফল্ট মানযুক্ত ফিল্ডগুলোর আগে থাকতে হবে।
defmodule Plane do
defstruct [:engine, wings: 2]
end
plane = %Plane{}
# => %Plane{engine: nil, wings: 2}
যেহেতু স্ট্রাক্ট ম্যাপের উপরে তৈরি, তাই মান পাওয়া ও পরিবর্তন করার জন্য আমরা বেশিরভাগ ম্যাপ ফাংশনই ব্যবহার করতে পারি। স্ট্রাক্টের জন্য Access Behaviour ইমপ্লিমেন্ট করা হয়নি। এর বদলে স্ট্রাক্টের ফিল্ড অ্যাক্সেস করতে static access operator . ব্যবহার করার পরামর্শ দেওয়া হয়।
ফিল্ডের মান get/fetch করা:
plane = %Plane{}
plane.engine
# => nil
Map.fetch(plane, :wings)
# => {:ok, 2}
ফিল্ডের মান আপডেট করা
plane = %Plane{}
%{plane | wings: 4}
# => %Plane{engine: nil, wings: 4}
স্ট্রাক্টের নাম দিয়ে বা নাম ছাড়াই স্ট্রাক্ট প্যাটার্ন ম্যাচিংয়ে ব্যবহার করা যায়।
plane = %Plane{}
%Plane{wings: wings} = plane
%{wings: wings} = plane
প্যাটার্নে স্ট্রাক্টের নাম যোগ করলে আপনি নিশ্চিত করতে পারেন যে বাম ও ডান দুই দিকেই একই টাইপের স্ট্রাক্ট আছে।
defmodule Helicopter do
defstruct [:engine, rotors: 1]
end
%Plane{} = %Helicopter{}
# => (MatchError) no match of right hand side value: %Helicopter{engine: nil, rotors: 1}
স্ট্রাক্ট তৈরি হওয়ার সময় মানগুলো ইনিশিয়ালাইজ হয়েছে কি না তা নিশ্চিত করতে আমরা ফিল্ডের কী (key)-গুলোর একটি লিস্টসহ @enforce_keys মডিউল অ্যাট্রিবিউট ব্যবহার করতে পারি। কোনো কী (key) লিস্টে না থাকলে তার মান nil হবে, যেমন উপরের উদাহরণে দেখা যায়। কোনো বাধ্যতামূলক কী (key) ইনিশিয়ালাইজ না হলে একটি এরর রেইজ হয়।
defmodule User do
@enforce_keys [:username]
defstruct [:username]
end
%User{}
# => (ArgumentError) the following keys must also be given when building struct User: [:username]
এই অনুশীলনীতে আপনি একটি রিমোট কন্ট্রোলড কার নিয়ে খেলবেন, যা কেনার জন্য অবশেষে যথেষ্ট টাকা জমিয়ে ফেলেছেন।
গাড়িগুলো সম্পূর্ণ (১০০%) চার্জের ব্যাটারি নিয়ে শুরু করে। প্রতিবার রিমোট কন্ট্রোল দিয়ে গাড়ি চালালে এটি ২০ মিটার যায় এবং ব্যাটারির এক শতাংশ কমে যায়। গাড়িটি তৈরি হওয়ার আগে তার ডাকনাম জানা যায় না।
এই রিমোট কন্ট্রোলড কারটিতে একটি দুর্দান্ত LED ডিসপ্লে আছে, যেখানে দুই ধরনের তথ্য দেখানো হয়:
"<METERS> meters"."Battery at <PERCENTAGE>%".ব্যাটারি ০% হলে আপনি আর গাড়ি চালাতে পারবেন না এবং ব্যাটারি ডিসপ্লেতে "Battery empty" দেখাবে।
RemoteControlCar.new/0 ফাংশনটি ইমপ্লিমেন্ট করুন যাতে এটি একেবারে নতুন একটি রিমোট কন্ট্রোলড কার স্ট্রাক্ট রিটার্ন করে:
RemoteControlCar.new()
# => %RemoteControlCar{
# battery_percentage: 100,
# distance_driven_in_meters: 0,
# nickname: "none"
# }
স্ট্রাক্টে ডাকনাম থাকা আবশ্যক, তাই নিশ্চিত করুন যে new ফাংশনে একটি মান ইনিশিয়ালাইজ করা হয়, স্ট্রাক্টে নয়।
RemoteControlCar.new/1 ফাংশনটি ইমপ্লিমেন্ট করুন যাতে এটি প্রদত্ত একটি ডাকনাম সহ একেবারে নতুন একটি রিমোট কন্ট্রোলড কার স্ট্রাক্ট রিটার্ন করে:
RemoteControlCar.new("Blue")
# => %RemoteControlCar{
# battery_percentage: 100,
# distance_driven_in_meters: 0,
# nickname: "Blue"
# }
RemoteControlCar.display_distance/1 ফাংশনটি ইমপ্লিমেন্ট করুন যাতে এটি LED ডিসপ্লেতে যেভাবে দেখানো হয় সেই অনুযায়ী দূরত্ব রিটার্ন করে:
car = RemoteControlCar.new()
RemoteControlCar.display_distance(car)
# => "0 meters"
নিশ্চিত করুন যে ফাংশনটি আর্গুমেন্ট হিসেবে শুধুমাত্র একটি RemoteControlCar স্ট্রাক্ট গ্রহণ করে।
RemoteControlCar.display_battery/1 ফাংশনটি ইমপ্লিমেন্ট করুন যাতে এটি LED ডিসপ্লেতে যেভাবে দেখানো হয় সেই অনুযায়ী ব্যাটারির শতাংশ রিটার্ন করে:
car = RemoteControlCar.new()
RemoteControlCar.display_battery(car)
# => "Battery at 100%"
নিশ্চিত করুন যে ফাংশনটি আর্গুমেন্ট হিসেবে শুধুমাত্র একটি RemoteControlCar স্ট্রাক্ট গ্রহণ করে। ব্যাটারি ০% হলে ব্যাটারি ডিসপ্লেতে "Battery empty" দেখাবে।
RemoteControlCar.drive/1 ফাংশনটি ইমপ্লিমেন্ট করুন যা:
RemoteControlCar.new("Red")
|> RemoteControlCar.drive()
# => %RemoteControlCar{
# battery_percentage: 99,
# distance_driven_in_meters: 20,
# nickname: "Red"
# }
নিশ্চিত করুন যে ফাংশনটি আর্গুমেন্ট হিসেবে শুধুমাত্র একটি RemoteControlCar স্ট্রাক্ট গ্রহণ করে।
RemoteControlCar.drive/1 ফাংশনটি এমনভাবে আপডেট করুন যাতে ব্যাটারি শেষ হয়ে গেলে (০% হলে) এটি চালিত দূরত্বও বাড়ায় না এবং ব্যাটারির শতাংশও কমায় না:
%RemoteControlCar{
battery_percentage: 0,
distance_driven_in_meters: 1980,
nickname: "Red"
}
|> RemoteControlCar.drive()
# => %RemoteControlCar{
# battery_percentage: 0,
# distance_driven_in_meters: 1980,
# nickname: "Red"
# }
Exercism-এ সাইন আপ করুন, Elixir ট্র্যাকের 58টি কনসেপ্ট168টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।