Rust में Question Mark Operator (?) क्या है? शुरुआती के लिए आसान व्याख्या
\n\nअगर आप Rust सीखना शुरू कर रहे हैं, तो आपने शायद कोड में एक अजीब सा ? चिन्ह देखा होगा। यह कुछ इस तरह दिखता है:
fn read_file(path: &str) -> Result<String, io::Error> {\n let mut file = File::open(path)?;\n let mut contents = String::new();\n file.read_to_string(&mut contents)?;\n Ok(contents)\n}\n\nया फिर इस तरह:
\n\nfn get_user_name(user_id: u32) -> Option<String> {\n let user = find_user(user_id)?;\n Some(user.name)\n}\n\nयह छोटा सा चिन्ह — question mark operator कहलाता है। शुरुआती लोगों को यह जादू जैसा लगता है: कोड छोटा और साफ हो जाता है, और एरर कहीं गायब हो जाती हैं। लेकिन असल में इस चिन्ह के पीछे क्या होता है? चलिए, इसे हमेशा के लिए समझ लेते हैं।
\n\nवैसे, यह सवाल इतना लोकप्रिय है कि Stack Overflow पर इसके हज़ारों व्यूज़ हैं। कोई आश्चर्य नहीं — ? ऑपरेटर आपके Rust कोड लिखने का तरीका ही बदल देता है।
आखिर Question Mark Operator की ज़रूरत क्यों है?
\n\nRust अपनी टाइप सिस्टम और सुरक्षा के लिए मशहूर है। इसमें Python या Java की तरह exceptions नहीं होते। इसके बजाय, एरर भी सिर्फ़ वैल्यू होती हैं। इसके लिए दो खास टाइप होते हैं:
\n\n- \n
Result<T, E>— ऑपरेशन सफल (Ok(T)) या एरर (Err(E)) के साथ खत्म हो सकता है। \n Option<T>— वैल्यू हो सकती है (Some(T)) या नहीं भी हो सकती (None)। \n
समस्या यह है कि इन टाइप को मैन्युअली हैंडल करना थकाऊ है। सोचिए, आपको एक फ़ाइल खोलनी है, उसे पढ़ना है, JSON पार्स करना है और नेटवर्क पर भेजना है। हर स्टेप पर एरर आ सकती है। ? के बिना, आपको match या unwrap के साथ ढेर सारा कोड लिखना पड़ता।
Question mark operator इस समस्या को बहुत ही सुंदर तरीके से हल करता है।
\n\n? ऑपरेटर कैसे काम करता है: सरल भाषा में
\n\nसमझिए कि ? ऑपरेटर एक स्मार्ट असिस्टेंट है जो कहता है:
- \n
- अगर सब कुछ ठीक है — मुझे वैल्यू दे दो, मैं आगे काम करूंगा। \n
- अगर कुछ गलत हुआ — मैं तुरंत करंट फंक्शन से एरर लौटा दूंगा। \n
आइए एक उदाहरण देखते हैं। पहले बिना question mark operator के:
\n\nuse std::fs::File;\nuse std::io::{self, Read};\n\nfn read_file(path: &str) -> Result<String, io::Error> {\n let file_result = File::open(path);\n \n let mut file = match file_result {\n Ok(f) => f,\n Err(e) => return Err(e),\n };\n \n let mut contents = String::new();\n let read_result = file.read_to_string(&mut contents);\n \n match read_result {\n Ok(_) => Ok(contents),\n Err(e) => return Err(e),\n }\n}\n\nऔर अब question mark operator के साथ:
\n\nuse std::fs::File;\nuse std::io::{self, Read};\n\nfn read_file(path: &str) -> Result<String, io::Error> {\n let mut file = File::open(path)?;\n let mut contents = String::new();\n file.read_to_string(&mut contents)?;\n Ok(contents)\n}\n\nफर्क ज़बरदस्त है। 15 लाइनों की जगह सिर्फ़ 5 लाइनें। और यह सिर्फ़ syntactic sugar नहीं है। ? ऑपरेटर कोड को ज़्यादा पढ़ने लायक और एरर-फ्री बनाता है।
गहराई में: अंडर द हुड क्या होता है
\n\nजब आप File::open(path)? लिखते हैं, तो Rust कंपाइलर इसे कुछ इस तरह से विस्तारित करता है:
match File::open(path) {\n Ok(val) => val,\n Err(err) => return Err(From::from(err)),\n}\n\nयहाँ From::from(err) पर ध्यान दें। यह सबसे अहम बिंदु है। ? ऑपरेटर सिर्फ़ एरर लौटाता नहीं है — यह From ट्रेट का उपयोग करके एरर टाइप को ऑटोमैटिकली कन्वर्ट करता है।
इसका व्यावहारिक मतलब क्या है? मान लीजिए,