किसी ऑब्जेक्ट के म्यूटेबल होने का क्या अर्थ है?
फैंसी शब्दों को आपको भ्रमित न करने दें, "म्यूटेबिलिटी" का सीधा सा अर्थ है कि किसी ऑब्जेक्ट की आंतरिक स्थिति को बदला जा सकता है। यह उन ऑब्जेक्ट्स को छोड़कर सभी ऑब्जेक्ट्स का डिफ़ॉल्ट है जिन्हें फ्रीज किया गया है, या जो विशेष ऑब्जेक्ट्स की सूची का हिस्सा हैं।
दूसरे शब्दों में, रूबी में सभी ऑब्जेक्ट्स म्यूटेबल नहीं हैं!
उदाहरण के लिए:
संख्याओं या प्रतीकों, या यहां तक कि true या false (जो ऑब्जेक्ट्स भी हैं) के लिए बदलना कोई मायने नहीं रखता।
संख्या 1 हमेशा 1 ही रहेगी।
लेकिन अन्य ऑब्जेक्ट्स, विशेष रूप से वे जो डेटा स्टोर करने के लिए होते हैं, जैसे Array या Hash ऑब्जेक्ट्स, को प्रदर्शन कारणों से बदलने की क्षमता होनी चाहिए।
विकल्प क्या है?
आप परिवर्तनों के साथ एक ऑब्जेक्ट की नई कॉपी बना सकते हैं और फिर इस नए ऑब्जेक्ट को वापस कर सकते हैं, मूल ऑब्जेक्ट को बरकरार रखते हुए।
यदि सरणियाँ इम्म्यूटेबल होतीं और आप सरणी के केवल एक एलिमेंट को बदलना चाहते, तो आपको सभी डेटा को कॉपी करना पड़ता, जिसमें वे एलिमेंट्स भी शामिल हैं जो नहीं बदले।
हर बार जब आपको कोई बदलाव करना हो, चाहे वह कितना भी छोटा क्यों न हो, दस लाख (या अधिक) एलिमेंट सरणी को कॉपी करने की कल्पना करें! बहुत कुशल नहीं…
वैसे भी।
आइए रूबी में म्यूटेबिलिटी कैसे काम करती है, इस पर थोड़ा और गहराई से नज़र डालते हैं।
म्यूटेबिलिटी और वेरिएबल्स पॉइंटर्स के रूप में
प्रोग्रामिंग त्रुटियों की एक श्रेणी है जो दो चीजों के संयोजन के कारण होती है:
- म्यूटेबल ऑब्जेक्ट्स।
- यह तथ्य कि वेरिएबल्स डेटा को सीधे नहीं रखते, बल्कि उस स्थान का संदर्भ रखते हैं जहां यह डेटा संग्रहीत है।
ये त्रुटियाँ एक तरीके से खुद को दिखाती हैं जब आप एक वेरिएबल को 'उपनाम' देने की कोशिश करते हैं।
यहां एक उदाहरण है:
name = "Peter" other_name = name puts other_name # "Peter"
इस उदाहरण में, दोनों name और other_name एक ही स्ट्रिंग ऑब्जेक्ट का संदर्भ रखते हैं। आप इस स्ट्रिंग की सामग्री को प्रदर्शित या संशोधित करने के लिए किसी का भी उपयोग कर सकते हैं।

समस्या तब आती है जब हम other_name को स्ट्रिंग की कॉपी की तरह मानते हैं।
other_name[0] = 'T' name # "Teter" other_name # "Teter"
चूंकि दोनों वेरिएबल्स एक ही स्ट्रिंग की ओर इशारा करते हैं, हमने अभी "Peter" को "Teter" में बदल दिया। यह एक समस्या है क्योंकि हम शायद "Peter" को बनाए रखना चाहते थे।
ऑब्जेक्ट्स को क्लोन करना
इस समस्या से निपटने का एक तरीका dup मेथड का उपयोग करना है।
यह रूबी को आपको ऑब्जेक्ट की एक कॉपी देने के लिए कहेगा। एक clone मेथड भी है, जो ऑब्जेक्ट की एक कॉपी देने के अलावा, फ्रीज स्टेटस और ऑब्जेक्ट पर परिभाषित किसी भी सिंगलटन मेथड को कॉपी करता है।
एक उदाहरण देखते हैं:
numbers = [1, 2, 3] more_numbers = numbers.dup more_numbers << 4 numbers # [1, 2, 3] more_numbers # [1, 2, 3, 4]
इस उदाहरण में, आप देख सकते हैं कि मूल numbers सरणी अपरिवर्तित रही। तीसरी पंक्ति पर उस dup कॉल को हटाकर देखें कि क्या होता है 🙂
रूबी फ्रीज मेथड
किसी ऑब्जेक्ट को अवांछित परिवर्तनों से सुरक्षित रखने का एक और तरीका है इसे 'फ्रीज' करना। किसी भी रूबी ऑब्जेक्ट को freeze मेथड का उपयोग करके फ्रीज किया जा सकता है।
जब कोई ऑब्जेक्ट फ्रीज हो जाता है, तो इस ऑब्जेक्ट को बदलने का कोई भी प्रयास RuntimeError अपवाद का परिणाम देगा।
नोट: आप
frozen?मेथड का उपयोग करके जांच सकते हैं कि कोई ऑब्जेक्ट फ्रीज है या नहीं।
उदाहरण:
animals = %w( cat dog tiger ) animals.freeze animals << 'monkey' # RuntimeError: can't modify frozen Array
एक बात ध्यान रखने योग्य है कि यह केवल एक ऑब्जेक्ट को फ्रीज करेगा, इस उदाहरण में सरणी ही, जो हमें इसमें आइटम जोड़ने या हटाने से रोकती है। लेकिन सरणी के अंदर के स्ट्रिंग्स फ्रीज नहीं हैं, इसलिए उन्हें अभी भी बदला जा सकता है!
animals[1][0] = 't' # => ["cat", "tog", "tiger"]
यदि आप स्ट्रिंग्स को फ्रीज करना चाहते हैं तो आपको उन पर freeze कॉल करना होगा। ऐसे: animals.each(&:freeze)।
फ्रोज़न स्ट्रिंग्स
म्यूटेबल ऑब्जेक्ट्स का प्रदर्शन पर भी प्रभाव पड़ता है, विशेष रूप से स्ट्रिंग्स पर। कारण यह है कि एक बड़े प्रोग्राम में इस बात की अच्छी संभावना है कि उसी स्ट्रिंग का कई बार उपयोग किया जाता है।
रूबी हर स्ट्रिंग के लिए एक नया ऑब्जेक्ट बनाएगा, भले ही दो स्ट्रिंग्स एक जैसी दिखें, या दूसरे शब्दों में, उनका वही 'कंटेंट' हो। आप irb में object_id मेथड का उपयोग करके इसे आसानी से होते हुए देख सकते हैं।
यहां एक उदाहरण है:
a = 'test' b = 'test' a.object_id # 76325640 b.object_id # 76317550
यह एक समस्या है क्योंकि ये ऑब्जेक्ट्स अतिरिक्त मेमोरी और अतिरिक्त CPU साइकिल्स का उपभोग कर रहे हैं।
रूबी 2.1 से शुरू करके, जब आप फ्रोज़न स्ट्रिंग्स का उपयोग करते हैं, तो रूबी उसी स्ट्रिंग ऑब्जेक्ट का उपयोग करेगा। यह उसी स्ट्रिंग की नई कॉपी बनाने से बचाता है। जिसके परिणामस्वरूप कुछ मेमोरी बचत और एक छोटा प्रदर्शन बूस्ट होता है।
रेल्स व्यापक रूप से फ्रोज़न स्ट्रिंग्स का उपयोग इसी कारण से करता है। उदाहरण के लिए, इस PR पर एक नज़र डालें।
इसने रूबी विकास टीम को स्ट्रिंग्स को डिफ़ॉल्ट रूप से इम्म्यूटेबल ऑब्जेक्ट्स में बदलने पर विचार करना शुरू कर दिया। वास्तव में, रूबी 2.3, जो कुछ दिन पहले जारी किया गया था, इसमें आपकी परियोजना के लिए इसे सक्षम करने के दो तरीके शामिल हैं।
एक है हर उस फाइल के शीर्ष पर # frozen_string_literal: true शामिल करना जहां आप स्ट्रिंग्स को इम्म्यूटेबल चाहते हैं। और दूसरा कमांड-लाइन आर्गुमेंट --enable=frozen-string-literal का उपयोग करना है।
डिफ़ॉल्ट रूप से इम्म्यूटेबल स्ट्रिंग्स शायद रूबी 3.0 में आएंगे।
अब पागल मत हो जाओ और अपने ऐप में अपनी सभी स्ट्रिंग्स को फ्रीज करना शुरू मत करो। आप केवल उन्हीं स्ट्रिंग्स के लिए ऐसा करना चाहते हैं जिनका सैकड़ों बार उपयोग किया जाता है ताकि किसी प्रकार का लाभ दिखाई दे। ऐसा कहने के बाद, यहां एक टूल है जिसका उपयोग आप संभावित स्ट्रिंग्स को फ्रीज करने के लिए ढूंढने के लिए कर सकते हैं।
अपने मेथड्स को जानें
म्यूटेबल ऑब्जेक्ट में सभी मेथड्स वास्तव में ऑब्जेक्ट को नहीं बदलेंगे, उदाहरण के लिए, gsub मेथड एक नई स्ट्रिंग लौटाएगा, मूल को अछूता छोड़ देगा।
इनमें से कुछ मेथड्स का एक वैकल्पिक संस्करण होता है जो मूल ऑब्जेक्ट को इन-प्लेस बदलता है, जो अक्सर अधिक कुशल होता है। ये मेथड्स अक्सर एक विस्मयादिबोधक प्रतीक ! के साथ समाप्त होते हैं उनके प्रभाव को इंगित करने के लिए।
इन 'बैंग' मेथड्स के दो उदाहरण हैं gsub! और map!।
इसे नोट करें:
! में समाप्त होने वाला मेथड हमेशा यह नहीं दर्शाता कि यह 'ऑब्जेक्ट को बदलने वाला मेथड' है।
अधिक सामान्य शब्दों में, ! प्रतीक 'खतरे' को दर्शाने के लिए उपयोग किया जाता है। इसका एक उदाहरण exit! मेथड है, जो प्रोग्राम से तुरंत बाहर निकल जाएगा, किसी भी एग्जिट हैंडलर को नजरअंदाज करते हुए।
ऐसे मेथड्स भी हैं जो ऑब्जेक्ट को बदलते हैं और ! प्रतीक के साथ समाप्त नहीं होते। उदाहरण के लिए: delete, clear, push, concat, और कई और।
समापन
म्यूटेबिलिटी एक पेचीदा विषय हो सकता है, लेकिन चूंकि आपने यह पोस्ट पढ़ी है, आप अब इससे निपटने के लिए बेहतर तैयार हैं। रूबी डॉक्यूमेंटेशन देखें यदि आप सुनिश्चित नहीं हैं कि कोई मेथड क्या कर रहा है, यह आपको समस्याओं से बचने में मदद करेगा।
मुझे आशा है कि आपको यह लेख जानकारीपूर्ण लगा, कृपया इसे अपने दोस्तों के साथ शेयर करें ताकि वे भी इसका आनंद ले सकें। साथ ही नीचे मेरे न्यूज़लेटर में शामिल हों ताकि जब ऐसी सामग्री आए तो आप उससे न चूकें!