সম্প্রতি মোজোতে বৈশিষ্ট্যগুলি চালু করা হয়েছিল, তাই আমি ভেবেছিলাম আমি সেগুলি চেষ্টা করব৷ বর্তমানে, অন্তর্নির্মিত বৈশিষ্ট্যগুলির মধ্যে রয়েছে CollectionElement , Copyable , Destructable , Intable , Movable , Sized , এবং Stringable (মনে হচ্ছে "-able" প্রত্যয়টি এই নামকরণের রীতিতে একটি জিনিস!)
বৈশিষ্ট্যগুলি কাঠামোর উপর কাজ করে। একটি বৈশিষ্ট্য বাস্তবায়ন করার জন্য, আপনি কেবল একটি স্ট্রাকটে একটি পদ্ধতি যোগ করুন যা বৈশিষ্ট্যের সাথে মেলে; তারপর একটি প্যারামিটার হিসাবে বৈশিষ্ট্য নাম পাস:
@value struct Duck(Quackable): fn quack(self): print("Quack!")
মোজোতে @value
ডেকোরেটর স্ট্রাকটে __init__()
, __copyinit__()
এবং __moveinit__()
এর মতো জীবনচক্র পদ্ধতিগুলি সন্নিবেশিত করে, আমাদের জীবনকে কিছুটা সরল করে কারণ আমাদের নিজেদেরকে সেগুলি যোগ করতে হবে না।
মোজোর বৈশিষ্ট্যগুলি এখনও পদ্ধতিগুলির জন্য ডিফল্ট বাস্তবায়ন সমর্থন করে না, তাই, উপরের Quackable
পদ্ধতির মূল অংশে ...
আপনি pass
ব্যবহার করতে পারেন, যা পাইথনের মতো একই প্রভাব ফেলবে।
ভিন্ন নাম থাকা সত্ত্বেও, মোজোতে বৈশিষ্ট্যের প্রাথমিক পদ্ধতি আমাকে গো ইন্টারফেসের কথা মনে করিয়ে দেয়। গো-তে, আপনি একটি Duck
স্ট্রাকটকে সংজ্ঞায়িত করবেন এবং এর মতো একটি Quackable
ইন্টারফেস প্রয়োগ করবেন:
type Quackable interface { quack() }
এবং একটি কাঠামো তৈরি করতে যা এই ইন্টারফেসটিকে সন্তুষ্ট করে:
type Duck struct {} func (d Duck) quack() { fmt.Println("Quack!") }
এটি একটি মোজো বাস্তবায়নের সাথে তুলনা করুন:
trait Quackable: fn quack(self): ... @value struct Duck(Quackable): fn quack(self): print("Quack!")
আমি মনে করি মোজো সংস্করণটি আরও সংক্ষিপ্ত, quack()
পদ্ধতির সংজ্ঞাটি Duck
struct টাইপের ভিতরে স্থাপন করে। স্ট্রাকটে কাজ করার পাশাপাশি, মোজোতে বৈশিষ্ট্যগুলির জন্য একটি implements
কীওয়ার্ডের প্রয়োজন হয় না, ঠিক গো-তে।
মজার বিষয় হল, মোজো ডক্সে এই পয়েন্টটি তৈরি করা হয়েছে যে ডিফল্ট বাস্তবায়ন এখনও অনুমোদিত নয়, যার অর্থ ভবিষ্যতে তাদের অনুমতি দেওয়া হতে পারে। এর মানে হল যে মোজো গো থেকে ভিন্ন একটি পদ্ধতি অনুসরণ করতে পারে, যা একটি ইন্টারফেসকে সন্তুষ্ট করে এমন কাঠামোর উপর ফোকাস করে, এটি বাস্তবায়ন না করে।
গো-তে ডিফল্ট পদ্ধতি বাস্তবায়নের প্রয়োজন নেই, এবং এম্বেডিংয়ের সাথে একই রকম প্রভাব অর্জন করা হয়, কারণ ইন্টারফেস/বৈশিষ্ট্য বাস্তবায়ন কেবল একটি ধারণা যা Go-তে বিদ্যমান নেই। মোজোতে জিনিসগুলি আলাদা হতে পারে।
বৈশিষ্ট্য এবং ইন্টারফেসের মান হল কোড পুনরায় ব্যবহারযোগ্য করা। উদাহরণস্বরূপ, মোজোতে, আপনি এমন ফাংশন লিখতে পারেন যা বৈশিষ্ট্যের ধরনগুলিকে গ্রহণ করে...
fn make_it_quack[T: Quackable](could_be_duck: T): could_be_duck.quack()
এবং তারপরে বিভিন্ন স্ট্রাকটগুলি পাস করুন যা ইনপুট হিসাবে একই বৈশিষ্ট্য প্রয়োগ করে - সবকিছুই কাজ করবে! উদাহরণস্বরূপ, এখানে একটি Goose
struct যা Quackable
প্রয়োগ করে:
@value struct Goose(Quackable): fn quack(self): print("Honk!")
এবং এখানে, Goose
এবং Duck
উভয়ের জন্য make_it_quack
কল করার জন্য (মনে রাখবেন, আপনার প্রোগ্রামের এন্ট্রি পয়েন্ট হিসাবে আপনার মোজোতে main
ফাংশন প্রয়োজন):
def main(): make_it_quack(Duck()) make_it_quack(Goose())
এর আউটপুট হবে
Quack! Honk!
যদি আমি এমন কিছু পাস করার চেষ্টা করি যা make_it_quack
ফাংশনে Quackable
বৈশিষ্ট্যটি বাস্তবায়ন না করে, তাহলে ধরা যাক StealthCow
, প্রোগ্রামটি কম্পাইল করবে না:
@value struct StealthCow(): pass
make_it_quack(StealthCow())
নীচের ত্রুটি বার্তা আরও বর্ণনামূলক হতে পারে; হয়তো মোজো দল এটা উন্নত করবে?
error: invalid call to 'make_it_quack': callee expects 1 input parameter, but 0 were specified
একই যদি আমি Goose
থেকে quack
পদ্ধতিটি সরিয়ে ফেলি; এখানে, আমরা একটি সুন্দর, বর্ণনামূলক ত্রুটি পাই:
struct 'Goose' does not implement all requirements for 'Quackable' required function 'quack' is not implemented
বিশুদ্ধ পাইথন পদ্ধতির উপর এই ধরণের স্ট্যাটিক টাইপ চেক করার সুবিধা হল যে আমরা সহজেই ত্রুটিগুলি ধরতে পারি এবং প্রোডাকশনে কোনও ভুল শিপিং এড়াতে পারি কারণ কোডটি কেবল কম্পাইল করবে না।
মোজোর বৈশিষ্ট্যগুলি ইতিমধ্যেই উত্তরাধিকারকে সমর্থন করে, তাই আমাদের 'কোয়াকেবল' বৈশিষ্ট্য একটি 'শ্রবণযোগ্য' বৈশিষ্ট্যকে এভাবে প্রসারিত করতে পারে:
trait Audible: fn make_sound(self): ...
trait Quackable(Audible): fn quack(self): ...
এর মানে হল যে একটি Duck
স্ট্রাকটকে quack
এবং make_sound
উভয়ই প্রয়োগ করতে হবে Quackable
বৈশিষ্ট্যের সাথে সামঞ্জস্য করার জন্য।
এটি Go-তে "ইন্টারফেস এম্বেডিং" এর ধারণার মতো, যেখানে একটি নতুন ইন্টারফেস তৈরি করতে যা অন্যান্য ইন্টারফেস থেকে উত্তরাধিকারসূত্রে পাওয়া যায়, আপনি প্যারেন্ট ইন্টারফেসগুলিকে এভাবে এম্বেড করবেন:
type Quackable interface { Audible // includes methods of Audible in Quackable's method set }
বৈশিষ্ট্যগুলি স্ট্যাটিক পদ্ধতিগুলিকেও গ্রহণ করে যা একটি কাঠামোর উদাহরণ তৈরি না করে কাজ করে:
trait Swims: @staticmethod fn swim(): ... @value struct Duck(Quackable, Swims): fn quack(self): print("Quack!") @staticmethod fn swim(): print("Swimming")
fn make_it_swim[T: Swims](): T.swim()
আপনি এই মত একটি স্ট্যাটিক পদ্ধতি কল:
def main(): make_it_quack(Duck()) make_it_quack(Goose()) Duck.swim()
যা আউটপুট করবে:
Quack! Honk! Swimming
লক্ষ্য করুন যে শেষ পদ্ধতি কলে, একটি হাঁসের উদাহরণ তৈরি করা হয়নি। এইভাবে পাইথনের স্ট্যাটিক পদ্ধতিগুলি কাজ করে, অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং থেকে কিছুটা দূরে। মোজো এই পাইথন কার্যকারিতা তৈরি করে।
মজার বিষয় হল, একটি খালি interface{}
যা যেকোন ধরনের পাস করতে দেয় এবং Go Generics চালু হওয়ার আগে Go সম্প্রদায়ের কাছে জনপ্রিয় ছিল, একটি Mojo-টাইপড ফাংশন fn
এর সাথে কাজ করবে না।
আপনার স্ট্রাকটকে অন্তত একটি লাইফসাইকেল পদ্ধতি যেমন __len__
বা __str__
প্রয়োগ করতে হবে, যা এই ক্ষেত্রে এটিকে Sized
বা Stringable
এর সাথে সামঞ্জস্যপূর্ণ করে তুলবে, যা বৈশিষ্ট্যের ধরনগুলিকে স্বীকার করে এমন ফাংশনগুলির সাথে ব্যবহার করা হবে।
এটি আসলে একটি বাস্তব সীমাবদ্ধতা নয় এবং এটি মোজোতে অনেক অর্থবহ করে তোলে, যেহেতু, মোজোর সাথে, আপনার যদি গতিশীল টাইপিংয়ের প্রয়োজন হয়, আপনি কেবল আরও নমনীয় def
ফাংশনে ফিরে যেতে পারেন এবং তারপরে অজানাদের সাথে কাজ করার জন্য সাধারণ পাইথন জাদু প্রয়োগ করতে পারেন। প্রকার
আরও কঠোর Mojo fn
ফাংশনগুলি DynamicVector
মতো প্রকারগুলি ব্যবহার করে জেনেরিক স্ট্রাকটেও কাজ করে; এখানে যে সম্পর্কে আরো পড়ুন.
আরেকটি সীমাবদ্ধতা যা আমি দেখছি বৈশিষ্ট্যগুলির পরিবর্তে স্ট্রাকস এবং তাদের পদ্ধতিগুলির সাথে কাজ করতে হবে এবং এটি ক্লিন আর্কিটেকচার/বিভিন্ন অংশে কোড আলাদা করার ক্ষেত্রে একটি সম্ভাব্য বাধা।
গো বনাম মোজো স্ট্রাকট পদ্ধতি সংজ্ঞা সহ পূর্ববর্তী উদাহরণগুলির একটি বিবেচনা করুন:
type Duck struct {} func (d Duck) quack() { fmt.Println("Quack!") }
@value struct Duck(Quackable): fn quack(self): print("Quack!")
মোজো উদাহরণ, আরও পাইথন-সদৃশ সিনট্যাক্স অনুসরণ করে, পদ্ধতির সংজ্ঞাকে সরাসরি স্ট্রাকটের ভিতরে রাখে, যেখানে গো সংস্করণ এটিকে স্ট্রাকট থেকে আলাদা করার অনুমতি দেয়। এই সংস্করণে, যদি আমার অনেক প্রকার এবং পদ্ধতি সহ একটি খুব দীর্ঘ কাঠামো থাকে তবে এটি পড়া কিছুটা কঠিন হবে।
যদিও এটি একটি সমালোচনামূলক পার্থক্য নয়, শুধুমাত্র সচেতন হতে হবে।
মোজো বৈশিষ্ট্যগুলি ইতিমধ্যেই বেশ কার্যকরী, যদিও ভাষাটি তার প্রথম দিনগুলিতে ছিল। যদিও গো দর্শনটি সরলতার বিষয়ে এবং বৈশিষ্ট্যগুলিকে ন্যূনতম রাখার চেষ্টা করে, এটি সম্ভবত আমরা ভবিষ্যতে মোজো বৈশিষ্ট্যগুলিতে আরও কার্যকারিতা যুক্ত দেখতে পাব, যা তাদের আরও শক্তিশালী করে তুলবে এবং বিভিন্ন ব্যবহারের ক্ষেত্রে টন সক্ষম করে তুলবে৷