Rust में Immutable बनाम const: अनुभवी डेवलपर्स भी क्यों भ्रमित हो जाते हैं?
\n\nक्या आपने कभी Rust में कोड लिखा है और अचानक सोचा है: "रुको, मैंने let के माध्यम से एक वेरिएबल घोषित किया, यह अपरिवर्तनीय है। और const भी एक कॉन्स्टेंट की तरह है। तो फिर अंतर क्या है?"। यदि हाँ, तो आप अकेले नहीं हैं। Stack Overflow पर "Rust में immutable और const वेरिएबल्स में क्या अंतर है?" प्रश्न ने हज़ारों व्यूज़ प्राप्त किए हैं। और यह कोई संयोग नहीं है।
पहली नज़र में ऐसा लगता है कि let x = 5 और const X: i32 = 5 दोनों एक ही काम करते हैं: मान बदलने पर रोक लगाते हैं। लेकिन Rust में, एक भाषा जहां मेमोरी सुरक्षा और प्रदर्शन सर्वोपरि हैं, बारीकियों में ही असली बात छिपी है। 2025 में, इन बारीकियों को समझना केवल सिद्धांत नहीं, बल्कि कुशल और मुहावरेदार कोड लिखने के लिए एक आवश्यकता है।
इस लेख में हम एक बार और हमेशा के लिए समझेंगे: immutable वेरिएबल और कॉन्स्टेंट में क्या अंतर है, कब क्या उपयोग करें, और अभी कौन से सर्वोत्तम अभ्यास प्रासंगिक हैं। चलिए शुरू करते हैं!
\n\n1. मूलभूत समझ: कंपाइलर क्या कहता है?
\n\nआइए सबसे सरल से शुरू करें। Rust में, वेरिएबल डिफ़ॉल्ट रूप से इम्यूटेबल (अपरिवर्तनीय) होते हैं। इसका मतलब है कि मान निर्दिष्ट करने के बाद आप इसे ओवरराइट नहीं कर सकते।
\n\nfn main() {\n let x = 5;\n // x = 6; // त्रुटि! immutable वेरिएबल को बदला नहीं जा सकता\n println!("x = {}", x);\n}\n\nऔर यहाँ कॉन्स्टेंट का एक उदाहरण है:
\n\nconst MAX_POINTS: u32 = 100_000;\n\nfn main() {\n println!("MAX_POINTS = {}", MAX_POINTS);\n}\n\nदेखने में - समान लगता है। लेकिन Rust कंपाइलर इन्हें पूरी तरह से अलग तरीके से संसाधित करता है। और यहीं से सबसे दिलचस्प शुरुआत होती है।
\n\n1.1. मुख्य अंतर #1: वे कहाँ रहते हैं?
\n\n- \n
let— एक वेरिएबल घोषित करता है। यह स्टैक (या हीप में, यदि यहBox,Stringआदि है) में मौजूद होता है और मेमोरी में इसका एक पता होता है। इसे संदर्भ द्वारा लिया जा सकता है, फ़ंक्शन में पास किया जा सकता है, स्थानांतरित किया जा सकता है। \n const— एक कॉन्स्टेंट घोषित करता है। इसका मेमोरी में कोई निश्चित पता नहीं होता है। कंपाइलर इसके मान को उपयोग के स्थान पर सीधे कोड में इनलाइन (एम्बेड) करता है। \n
यह एक मूलभूत अंतर है। const एक वेरिएबल नहीं है, यह एक नामित मान है जो संकलन चरण में प्रतिस्थापित किया जाता है।
fn main() {\n let x = 42;\n let y = &x; // ठीक है, वेरिएबल का संदर्भ ले रहे हैं\n\n const Z: i32 = 100;\n // let w = &Z; // त्रुटि! कॉन्स्टेंट का कोई पता नहीं है, संदर्भ नहीं लिया जा सकता\n}\n\n2. गहराई से समझना: प्रदर्शन और शब्दार्थ
\n\nअब जब हम "निवास स्थान" के बारे में जानते हैं, तो आइए अन्य महत्वपूर्ण पहलुओं पर चर्चा करें।
\n\n2.1. जीवनकाल और दृश्यता क्षेत्र
\nकॉन्स्टेंट वैश्विक दृश्यता क्षेत्र (या फ़ंक्शन के अंदर, लेकिन static जीवनकाल के साथ) में रहते हैं। वे प्रोग्राम के चलने के पूरे समय मौजूद रहते हैं। उन्हें फ़ंक्शन के बाहर घोषित किया जा सकता है, और वे हर जगह उपलब्ध होंगे।
Immutable वेरिएबल केवल ब्लॉक (फ़ंक्शन, लूप, if) के अंदर रहते हैं। जैसे ही ब्लॉक समाप्त होता है, मेमोरी मुक्त हो जाती है।
const GLOBAL_CONST: i32 = 10;\n\nfn main() {\n let local_var = 20;\n // local_var केवल main के अंदर रहता है\n}\n// local_var अब मौजूद नहीं है\n// GLOBAL_CONST अभी भी उपलब्ध है\n\n2.2. प्रकार और एनोटेशन
\nconst के लिए डेटा प्रकार निर्दिष्ट करना अनिवार्य है। let के लिए, कंपाइलर स्वयं इसे निकाल लेगा।
const PI: f64 = 3.14159; // अनिवार्य: const नाम: प्रकार = मान;\nlet pi = 3.14159; // कंपाइलर स्वयं समझ जाएगा कि यह f64 है\n\n2.3. संकलन चरण पर गणना (CTFE)
\nconst का मान संकलन चरण पर गणना किया जाना चाहिए।