Rust में वेरिएबल का प्रकार कैसे प्रदर्शित करें और भ्रमित न हों
\n\nक्या आपने कभी Rust में कोड लिखा है और अचानक यह सोचकर रुक गए हैं: "इस वेरिएबल का प्रकार क्या है?" यदि हाँ — तो आप अकेले नहीं हैं। Stack Overflow पर "How do I print the type of a variable in Rust" प्रश्न ने हजारों बार देखा गया है, और यह कोई संयोग नहीं है। Rust एक सख्त लेकिन बुद्धिमान प्रकार प्रणाली वाली भाषा है, और कभी-कभी कंपाइलर हमसे अधिक जानता है।
\n\nइस लेख में, हम वेरिएबल का प्रकार प्रदर्शित करने के तीन तरीकों पर चर्चा करेंगे: एक सरल डीबगिंग तकनीक से लेकर एक पेशेवर मैक्रो तक। आप जानेंगे कि कब कौन सी विधि का उपयोग करना है, और let x = ... के पीछे क्या छिपा है, इसका अनुमान लगाना बंद कर देंगे।
Rust आसानी से प्रकार क्यों प्रिंट नहीं करने देता?
\n\nPython या JavaScript जैसी भाषाओं में, आप print(type(x)) लिख सकते हैं — और बस। Rust में ऐसी सुविधा दो कारणों से उपलब्ध नहीं है:
- \n
- स्थैतिक टाइपिंग: प्रकार संकलन चरण में ज्ञात होते हैं, लेकिन प्रोग्रामर के लिए हमेशा स्पष्ट नहीं होते (विशेषकर क्लोजर या जटिल जेनेरिक के साथ काम करते समय)। \n
- रिफ्लेक्शन का अभाव: Rust डिफ़ॉल्ट रूप से रनटाइम पर प्रकारों के बारे में जानकारी संग्रहीत नहीं करता — इससे प्रदर्शन पर बोझ पड़ेगा। \n
लेकिन Rust डेवलपर्स ने हमारे लिए कुछ खामियाँ छोड़ी हैं। आइए उन पर नज़र डालें।
\n\nविधि 1: std::any::type_name — सबसे सरल (लेकिन आदर्श नहीं)
\n\nRust की मानक लाइब्रेरी std::any::type_name फ़ंक्शन प्रदान करती है। यह प्रकार के नाम के साथ एक स्ट्रिंग लौटाती है। यह इस प्रकार काम करता है:
use std::any::type_name;\n\nfn print_type<T>(_: &T) {\n println!("{}", type_name::<T>());\n}\n\nfn main() {\n let x = 42;\n let y = "hello";\n let z = vec![1, 2, 3];\n \n print_type(&x); // i32\n print_type(&y); // &str\n print_type(&z); // Vec<i32>\n}\n\nलाभ:
\n- \n
- न्यूनतम कोड — बॉक्स से बाहर काम करता है। \n
- डीबगिंग और त्वरित जाँच के लिए उपयुक्त। \n
नुकसान:
\n- \n
- परिणाम कंपाइलर पर निर्भर करता है: Rust के विभिन्न संस्करणों या विभिन्न प्लेटफार्मों पर स्ट्रिंग भिन्न हो सकती है। \n
- प्रोडक्शन लॉजिक में उपयोग नहीं किया जा सकता, जहाँ प्रकार के आधार पर निर्णय लेने की आवश्यकता होती है। \n
लाइव उदाहरण: जटिल अभिव्यक्ति की डीबगिंग
\n\nकल्पना करें कि आप इटरेटर और मेथड चेन के साथ काम कर रहे हैं। अंत में कौन सा प्रकार प्राप्त होगा?
\n\nuse std::any::type_name;\n\nfn main() {\n let data = vec![1, 2, 3, 4, 5];\n let result = data.iter()\n .filter(|x| *x % 2 == 0)\n .map(|x| x * 2)\n .collect::<Vec<_>>();\n \n // क्या हम collect से पहले प्रकार जानना चाहते हैं?\n let intermediate = data.iter()\n .filter(|x| *x % 2 == 0)\n .map(|x| x * 2);\n \n println!("intermediate का प्रकार: {}", type_name::<decltype!(intermediate)>()); \n // उफ़, यह काम नहीं करेगा — संदर्भ पास करना होगा\n println!("intermediate का प्रकार: {}", type_name_of_val(&intermediate));\n}\n\nfn type_name_of_val<T>(_: &T) -> &str {\n type_name::<T>()\n}\n\nयह तरकीब आपको तब बचाएगी जब कंपाइलर कोई त्रुटि देता है और आप समझ नहीं पाते कि वह किस प्रकार की अपेक्षा कर रहा है।
\n\nविधि 2: कंपाइलर त्रुटियों का उपयोग करें — एक चालाक ट्रिक
\n\nकभी-कभी प्रकार जानने का सबसे अच्छा तरीका कंपाइलर को स्वयं बताने के लिए मजबूर करना है। एक पुरानी लेकिन काम करने वाली ट्रिक है: वेरिएबल को एक अस्तित्वहीन प्रकार असाइन करना।
\n\nfn main() {\n let x = 42;\n let y: () = x; // त्रुटि! expected (), found i32\n}\n\nकंपाइलर कुछ इस प्रकार आउटपुट देगा:
\nerror[E0308]: mismatched types\n --> src/main.rs:3:18\n |\n3 | let y: () = x;\n | -- ^ expected `()`, found `i32`\n | |\n | expected due to this\n\nलाभ:
\n- \n
- इम्पोर्ट की आवश्यकता नहीं है। \n
- std (no_std) के बिना वातावरण में भी काम करता है। \n