আপনি যদি রুবি 3x3 প্রচেষ্টা অনুসরণ করে থাকেন তবে আপনি সম্ভবত Optcarrot সম্পর্কে শুনেছেন। এটি খাঁটি রুবিতে লেখা একটি NES এমুলেটর।
আমি সম্প্রতি Optcarrot উত্সটি দেখছিলাম এবং একটি আকর্ষণীয় বিশদ আমার কাছে আটকে গেল। এটি রুবির হ্যাশের একটি বৈশিষ্ট্যের ব্যাপক ব্যবহার করে যা প্রায়শই উপেক্ষা করা হয়, কিন্তু বেশ দরকারী। যে কোনো বস্তুকে হ্যাশ কী হিসেবে ব্যবহার করার ক্ষমতা।
প্রসঙ্গ:NES মেমরি ম্যাপিং
উচ্চ-স্তরের প্রোগ্রামার হিসাবে, আমরা মেমরিকে RAM হিসাবে ভাবি। কিন্তু একটি নিম্ন স্তরে, "মেমরি" এর আরও অনেক ব্যবহার রয়েছে।
NES-এর CPU কিভাবে GPU, কন্ট্রোল প্যাড এবং কার্টিজের কোন বিশেষ ইলেকট্রনিক্সের সাথে যোগাযোগ করে তা হল "মেমরি"-তে পড়া এবং লেখা। ব্যবহৃত ঠিকানার উপর নির্ভর করে, একটি write_to_memory
মেথড কল জয়স্টিক রিসেট করতে পারে, VRAM অদলবদল করতে পারে বা একটি শব্দ চালাতে পারে।
আপনি কিভাবে রুবিতে এটি বাস্তবায়ন করবেন?
Optcarrot এটি দুটি Method
সংরক্ষণ করে করে প্রতিটি 65536 ঠিকানার জন্য বস্তু। একজন হল গেটার এবং একজন সেটার। এটা এই মত কিছু দেখায়:
@getter_methods[0x0001] = @ram.method(:[])
@setter_methods[0x0001] = @ram.method(:[]=)
সমস্যা:ডুপ্লিকেট অবজেক্ট
Object#method
ব্যবহারে সমস্যা এইভাবে এটি অনেকগুলি পৃথক Method
তৈরি করে বস্তু যা অভিন্ন।
আমরা object_id
দেখে এটি দেখতে পারি :
> a = []
> a.method(:[]=).object_id
=> 70142391223600
> a.method(:[]=).object_id
=> 70142391912420
দুটি Method
বস্তুর আলাদা object_id
আছে মান, তাই তারা ভিন্ন বস্তু যদিও তারা একই জিনিস করে।
সাধারণত, আমরা কিছু অতিরিক্ত Method
সম্পর্কে চিন্তা করি না বস্তু, কিন্তু এই ক্ষেত্রে আমরা তাদের হাজার হাজার সঙ্গে ডিল করছি.
সমাধান:হ্যাশের মাধ্যমে স্মরণ করা
Optcarrot ডুপ্লিকেট Method
এড়িয়ে যায় একটি কৌশলের সাথে বস্তুর সমস্যা যা এত সহজ যে এটি উপেক্ষা করা সহজ।
এটি একটি হ্যাশ ব্যবহার করে মেমোাইজ এবং ডিডপ্লিকেট করতে। নীচের সরলীকৃত কোডটি কৌশলটি প্রদর্শন করে:
def initialize
@setter_methods = []
@setter_cache = {}
...
end
def add_setter(address, setter)
# Doesn't store duplicates
@setter_cache[setter] ||= setter
# Use the deduped version
@setter_methods[address] = @setter_cache[setter]
end
এটি কাজ করে কারণ Hash
আপনি কী ধরনের বস্তু এটিকে কী হিসেবে দেন তাতে কিছু যায় আসে না।
যদি এটি বিভ্রান্তিকর হয়, IRB-তে স্ট্রিং দিয়ে চেষ্টা করুন:
> cache = {}
> cache["foo"] ||= "bar"
=> "bar"
cache["foo"] ||= "baz"
=> "bar"
এখন, বিবেচনা করুন যে রুবিতে, স্ট্রিং হল ক্লাস String
এর উদাহরণ . একটি হ্যাশ কী হিসাবে স্ট্রিং ব্যবহার করার জন্য রুবি যে পদ্ধতিটি ব্যবহার করা হয় তা মূলত একটি Method
সংরক্ষণ করার জন্য ব্যবহৃত হয়। বস্তু
হ্যাশ কিভাবে সমতা গণনা করে
হ্যাশ কী হিসাবে নন-স্ট্রিং অবজেক্ট ব্যবহার করার সময়, প্রশ্ন ওঠে:কিভাবে Hash
করে দুটি বস্তু সমান কিনা জানেন?
উত্তর হল এটি Object#hash
ব্যবহার করে পদ্ধতি এই পদ্ধতিটি আপনার বস্তুর মধ্য দিয়ে যায় এবং পুনরাবৃত্তিমূলকভাবে একটি হ্যাশ তৈরি করে। এটা এই মত দেখায়:
> a.method(:[]=).hash
=> 929915641391564853
কারণ অভিন্ন বস্তু অভিন্ন হ্যাশ মান উত্পাদন করে এটি সমতার পরীক্ষা হিসাবে ব্যবহার করা যেতে পারে।
a.hash == b.hash
যথেষ্ট আকর্ষণীয়, এটি eql?
দ্বারা ব্যবহৃত একই পদ্ধতি পদ্ধতি:
a.eql?(b)
এটি Method
এর সাথে কাজ করে আমাদের উদাহরণে অবজেক্ট:
> a.method(:[]=).hash == a.method(:[]=).hash
=> true
উপসংহার
রুবি ওয়েব ডেভেলপমেন্ট প্যাটার্নে অভ্যস্ত হওয়ার পর, অপটক্যারট সোর্সটি দেখা এবং একটি রিয়েল-টাইম নন-ওয়েব অ্যাপ কীভাবে বিভিন্ন প্যাটার্ন ব্যবহার করে তা দেখা আমার জন্য সত্যিই আকর্ষণীয় ছিল। একটি ওয়েব অ্যাপে আমি সন্দেহ করি যে আমি কখনও 65536 উপাদানগুলির সাথে একটি অ্যারে তৈরি করব, তবে এখানে, একটি "ডেস্কটপ" অ্যাপের সেটআপের অংশ হিসাবে, এটি অনেক অর্থবহ করে তোলে।
আপনার কোন প্রশ্ন বা মন্তব্য থাকলে, অনুগ্রহ করে টুইটারে [email protected] বা @StarrHorne-এ যোগাযোগ করুন।