यदि आप रूबी 3x3 प्रयास का अनुसरण कर रहे हैं, तो आपने शायद Optcarrot के बारे में सुना होगा। यह शुद्ध रूबी में लिखा गया एक एनईएस एमुलेटर है।
मैं हाल ही में Optcarrot स्रोत को देख रहा था और एक दिलचस्प विवरण मेरे सामने आया। यह रूबी के हैश की एक विशेषता का व्यापक उपयोग करता है जिसे अक्सर अनदेखा किया जाता है, लेकिन काफी उपयोगी होता है। वह हैश कुंजी के रूप में किसी भी वस्तु का उपयोग करने की क्षमता है।
संदर्भ:NES मेमोरी मैपिंग
उच्च-स्तरीय प्रोग्रामर के रूप में, हम मेमोरी को रैम के रूप में सोचते हैं। लेकिन निचले स्तर पर, "स्मृति" के कई अन्य उपयोग हैं।
"मेमोरी" को पढ़ना और लिखना यह है कि एनईएस का सीपीयू जीपीयू, कंट्रोल पैड और कार्ट्रिज पर किसी विशेष इलेक्ट्रॉनिक्स के साथ कैसे संचार करता है। उपयोग किए गए पते के आधार पर, एक write_to_memory
विधि कॉल जॉयस्टिक को रीसेट कर सकता है, वीआरएएम को स्वैप कर सकता है या ध्वनि चला सकता है।
आप इसे रूबी में कैसे लागू करेंगे?
Optcarrot दो Method
storing को संग्रहित करके करता है 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
class वर्ग के उदाहरण हैं . रूबी का उपयोग हैश कुंजी के रूप में स्ट्रिंग का उपयोग करने के लिए किया जाता है, मूल रूप से वही है जो 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 तत्वों के साथ एक सरणी बनाउंगा, लेकिन यहां, "डेस्कटॉप" ऐप के लिए सेटअप के हिस्से के रूप में, यह बहुत समझ में आता है।
यदि आपका कोई प्रश्न या टिप्पणी है, तो कृपया Twitter पर [email protected] या @StarrHorne पर संपर्क करें।