Rust "hello" के साथ String की तुलना क्यों नहीं करने देता?
\n\nयदि आप अभी Rust सीखना शुरू कर रहे हैं और पहले से ही String प्रकार के वेरिएबल को किसी स्ट्रिंग लिटरल जैसे "hello" या "world" से मिलान करने की आवश्यकता का सामना कर चुके हैं, तो आपने शायद कंपाइलर की एक अजीब त्रुटि देखी होगी। आप कुछ इस तरह लिखते हैं:
let user_input = String::from("start");\nmatch user_input {\n "start" => println!("शुरू करें!"),\n "stop" => println!("रोकें!"),\n _ => println!("अज्ञात कमांड"),\n}\n\n\nऔर कंपाइलर कुछ इस तरह देता है: "expected struct `String`, found `&str`"। परिचित लगता है?
\n\nStack Overflow पर प्रश्न "How to match a String against string literals?" को हजारों बार देखा गया है - यह शुरुआती लोगों के लिए एक वास्तविक दर्द है। इस लेख में, हम समझेंगे कि ऐसा क्यों होता है, और समस्या को हल करने के तीन सरल तरीके दिखाएंगे। आप सीखेंगे कि Rust में स्वामित्व और उधार प्रणाली व्यवहार में कैसे काम करती है, और कंपाइलर त्रुटियों से डरना बंद कर देंगे।
\n\nसंघर्ष की प्रकृति: String बनाम &str
\n\nसमस्या को समझने के लिए, मूल बातें याद रखना आवश्यक है। Rust में टेक्स्ट के साथ काम करने के लिए दो मुख्य प्रकार हैं:
\n\n- \n
String- यह एक स्वामित्व वाली स्ट्रिंग है, जो हीप में संग्रहीत होती है। यह बदल सकती है, बढ़ सकती है और घट सकती है। उदाहरण:let s = String::from("hello");\n &str- यह एक स्ट्रिंग स्लाइस है। यह स्ट्रिंग के एक भाग (या स्ट्रिंग लिटरल, जो सीधे प्रोग्राम के बाइनरी में संग्रहीत होता है) का संदर्भ है। उदाहरण:"hello"वास्तव में&'static strहै। \n
जब आप match user_input { "start" => ... } लिखते हैं, तो आप String की तुलना &str से करने का प्रयास कर रहे हैं। कंपाइलर कहता है: "मैं नहीं जानता कि उन्हें सीधे कैसे मिलान किया जाए, प्रकार अलग हैं!" और यह अच्छा है - Rust आपको अंतर्निहित रूपांतरणों से बचाता है जो प्रदर्शन हानि या छिपी बग का कारण बन सकते हैं।
लेकिन फिर क्या करें? तीन सरल और सुरुचिपूर्ण समाधान हैं।
\n\nसमाधान 1: as_str() के माध्यम से उधार लेना
\n\nसबसे सीधा और समझने योग्य तरीका है as_str() विधि का उपयोग करके String से एक स्ट्रिंग स्लाइस (&str) प्राप्त करना। यह विधि स्ट्रिंग की सामग्री का एक संदर्भ लौटाती है, बिना उसकी प्रतिलिपि बनाए। यह इस तरह दिखता है:
fn main() {\n let command = String::from("start");\n\n match command.as_str() {\n "start" => println!("सिस्टम शुरू हो रहा है..."),\n "stop" => println!("रोका जा रहा है..."),\n "pause" => println!("विराम..."),\n _ => println!("अज्ञात कमांड: {}", command),\n }\n}\n\n\nयह क्यों काम करता है? as_str() एक &str लौटाता है, जिसकी अब लिटरल से तुलना की जा सकती है। Rust देखता है कि दोनों ऑपरेंड &str हैं, और पैटर्न मिलान पूरी तरह से काम करता है।
लाभ: सरलता, पठनीयता, शून्य ओवरहेड (उधार, प्रतिलिपि नहीं)।
\n\nनुकसान: विधि को कॉल करना याद रखना होगा। लेकिन यह एक छोटी सी बात है।
\n\nसमाधान 2: if शर्त में तुलना
\n\nयदि आपको match की पूरी शक्ति की आवश्यकता नहीं है, तो आप eq() विधि या == ऑपरेटर के साथ सामान्य if का उपयोग कर सकते हैं। Rust PartialEq ट्रेट के माध्यम से String और &str की तुलना कर सकता है, जो प्रकारों के इस जोड़े के लिए कार्यान्वित किया गया है।
fn main() {\n let user_input = String::from("admin");\n\n if user_input == "admin" {\n println!("पहुँच अनुमत!");\n } else if user_input == "guest" {\n println!("अतिथि पहुँच");\n } else {\n println!("गलत लॉगिन");\n }\n}\n\n\nयह काम करता है क्योंकि कंपाइलर तुलना करते समय स्वचालित रूप से String को &str में बदल देता है। लेकिन match में ऐसा कोई रूपांतरण नहीं है - वहाँ सटीक मिलान की आवश्यकता होती है।