Rust में उत्परिवर्तन: कोलन से पहले या बाद में? अंदरूनी विश्लेषण

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

परिचय: दो «mut» की पहेली

\n

यदि आपने कभी Rust में कोड लिखा है, तो आपने निश्चित रूप से कीवर्ड mut की अजीब द्वैतता देखी होगी। यह वेरिएबल के नाम से पहले (let mut x = 5) और कोलन के बाद, प्रकार के साथ (&mut T) दोनों जगह आ सकता है। पहली नज़र में यह एक छोटी सी बात है, लेकिन Stack Overflow पर इस विषय ने हज़ारों व्यूज़ जुटाए हैं। क्यों? क्योंकि इस छोटी सी बात के पीछे स्वामित्व और संदर्भ के बीच एक मूलभूत अंतर छिपा है।

\n

इस लेख में हम केवल «mut कहाँ लगाएँ?» प्रश्न का उत्तर नहीं देंगे। हम Rust के अंदरूनी भाग में झाँकेंगे, समझेंगे कि कंपाइलर उत्परिवर्तनीयता को कैसे संभालता है, और यह अंतर सुरक्षित मेमोरी प्रबंधन की कुंजी क्यों है। यदि आप Rust सीख रहे हैं या इसके स्वामित्व मॉडल को गहराई से समझना चाहते हैं, तो यह लेख आपके लिए है।

\n\n

मुख्य भाग: दो दुनियाएँ — दो mut

\n

1. पहला mut: «मैं मालिक हूँ और बदल सकता हूँ»

\n

जब आप लिखते हैं:

\n
let mut x = 42;\nx = 10; // ठीक है\n
\n

तो आप कंपाइलर से कह रहे हैं: «मैं एक वेरिएबल x बना रहा हूँ, जो मान 42 का मालिक है, और मैं भविष्य में इस मान को बदलने की अनुमति देता हूँ»। mut के बिना, वेरिएबल डिफ़ॉल्ट रूप से अपरिवर्तनीय (इम्यूटेबल) होता है। यह Rust का एक सोचा-समझा डिज़ाइन चुनाव है: डिफ़ॉल्ट रूप से सुरक्षा, और उत्परिवर्तन एक स्पष्ट अनुमति है।

\n

अंदरूनी भाग: कंपाइलर स्टैक (या हीप, यदि यह Box है) पर जगह आवंटित करता है और मेमोरी सेल को «परिवर्तनीय» के रूप में चिह्नित करता है। उधार जाँचकर्ता (borrow checker) यह सुनिश्चित करेगा कि आपके पास एक ही समय में इस मेमोरी पर परिवर्तनीय और अपरिवर्तनीय दोनों संदर्भ न हों। यदि mut नहीं होता, तो कोई भी नया मान निर्दिष्ट करने का प्रयास संकलन त्रुटि उत्पन्न करता।

\n\n

2. दूसरा mut: «मैं तुम्हें चाबियाँ दे रहा हूँ, लेकिन घर नहीं दे रहा»

\n

अब संदर्भ के साथ एक उदाहरण:

\n
let mut x = 42;\nlet y = &mut x; // x पर परिवर्तनीय संदर्भ\n*y = 100;\n
\n

यहाँ &mut T स्वामित्व के बारे में नहीं है, बल्कि उधार लेने के बारे में है। हम कह रहे हैं: «मैं x को वेरिएबल y को उधार दे रहा हूँ, और इसे बदलने का अधिकार भी दे रहा हूँ»। x स्वयं मालिक बना रहता है, लेकिन अस्थायी रूप से नियंत्रण स्थानांतरित करता है।

\n

मुख्य अंतर: कोलन के बाद का mut वेरिएबल के बजाय संदर्भ के प्रकार से संबंधित है। आप let &mut x = &y नहीं लिख सकते — यह वाक्य-रचना की दृष्टि से गलत है। Rust सख्ती से अंतर करता है:

\n
    \n
  • let mut x — परिवर्तनीय मालिक वेरिएबल
  • \n
  • &mut T — प्रकार T के किसी मान पर परिवर्तनीय संदर्भ
  • \n
\n

यही अंतर शुरुआती लोगों को भ्रमित करता है: देखने में «mut» अलग-अलग जगहों पर है, जबकि अर्थ की दृष्टि से यह अलग-अलग कार्य करता है।

\n\n

3. यह क्यों महत्वपूर्ण है: borrow checker

\n

कल्पना करें कि आप एक फ़ंक्शन लिख रहे हैं जो एक संदर्भ लेता है:

\n
fn increment(n: &mut i32) {\n    *n += 1;\n}\n\nfn main() {\n    let mut a = 5;\n    increment(&mut a);\n    println!("{}", a); // 6\n}\n
\n

यदि हम fn increment(n: &i32) (mut के बिना) लिखते, तो हम n को बदल नहीं पाते। और यदि हम a में mut भूल जाते, तो हम परिवर्तनीय संदर्भ पास नहीं कर पाते। Rust कंपाइलर आपको डेटा में आकस्मिक परिवर्तन से बचाता है, जो डेटा रेस या अनिर्धारित व्यवहार का कारण बन सकता है।

\n

अंदरूनी भाग: &mut T एक अद्वितीय (अनन्य) संदर्भ है। किसी भी समय डेटा पर केवल एक ही परिवर्तनीय संदर्भ मौजूद हो सकता है। यह नियम सुनिश्चित करता है कि जब आप डेटा बदल रहे हैं, तो कोई और उसे नहीं पढ़ रहा है। अपरिवर्तनीय संदर्भों की संख्या असीमित हो सकती है — वे केवल पढ़ते हैं।

\n\n

4. व्यवहार में एक वास्तविक उदाहरण: स्ट्रक्चर और विधियाँ

\n

अक्सर भ्रम विधियों के साथ काम करते समय उत्पन्न होता है:

\n
struct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Point {\n    fn shift(&mut self, dx: i32, dy: i32) {\n        self.x += dx;\n        self.y += dy;\n    }\n}\n\nfn main() {\n    let mu                

ब्लॉग

पुस्तक अनुशंसाएँ