Rust में संख्याओं का सुरक्षित रूपांतरण: शुरुआती के लिए पूरी गाइड

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

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

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

परिचय: Rust में संख्याओं का रूपांतरण क्यों ज़रूरी है?

\n

क्या आपने कभी Python में int_var = 3.14 लिखा और फिर float_var = int_var किया? Python में यह काम करता है क्योंकि वहाँ types dynamic होते हैं। लेकिन Rust एक सख्त घड़ीसाज़ की तरह है - हर पुर्जा अपने सही आकार का होना चाहिए। अगर आप u8 (0–255) को u16 में डालते हैं तो एक बात है, लेकिन उल्टा करने पर डेटा चुपचाप खत्म हो सकता है या panic हो सकता है।

\n

Stack Overflow पर सवाल «How do I convert between numeric types safely and idiomatically?» को हज़ारों बार देखा गया है। यह कोई संयोग नहीं है: शुरुआती अक्सर as, From और TryFrom के बीच भ्रमित हो जाते हैं। इस लेख में हम Rust में संख्याओं को बदलने के सभी तरीकों को सरलता से समझाएँगे, बताएँगे कि कब किसका उपयोग करें, और ऐसे उदाहरण देंगे जिन्हें आप तुरंत अपना सकते हैं।

\n\n

1. as से सरल रूपांतरण: तेज़ लेकिन खतरनाक

\n

सबसे आसान तरीका है as ऑपरेटर। यह काम करता है, लेकिन इसमें छिपे खतरे हैं।

\n
let big: u32 = 300;\nlet small: u8 = big as u8; // 300, u8 में फिट नहीं होता!\nprintln!("{}", small); // आउटपुट: 44 (300 mod 256)\n
\n

क्या हुआ? Rust ने 300 (0b1_0010_1100) के सिर्फ आखिरी 8 bits लिए और बाकी छोड़ दिए, जिससे 0b0010_1100 = 44 बचा। इसे truncation (काट-छाँट) कहते हैं। u8 के लिए यह अप्रत्याशित हो सकता है।

\n

as सिर्फ type बढ़ाने पर सुरक्षित है (जैसे u8 → u16), जब value निश्चित रूप से फिट हो। छोटा करने पर यह एक टाइम बम है।

\n

as कब उपयोग करें? सिर्फ तब जब आपको पूरा यकीन हो कि value target type की सीमा से बाहर नहीं जाएगी। जैसे bit masks या low-level protocols के साथ काम करते समय।

\n\n

2. सही तरीका: From और Into traits

\n

Rust एक ऐसी भाषा है जहाँ गलतियाँ स्पष्ट होनी चाहिए। इसलिए standard library From और Into traits प्रदान करती है सुरक्षित रूपांतरण के लिए, जो कभी fail नहीं होता।

\n

नियम सरल है: अगर रूपांतरण हमेशा सफल होता है (डेटा लॉस नहीं), तो trait लागू है। उदाहरण:

\n
let small: u8 = 42;\nlet big: u16 = small.into(); // Into अपने आप From को कॉल करता है\n// या\nlet big: u16 = u16::from(small);\nprintln!("{}", big); // 42\n
\n

ध्यान दें: From सिर्फ उन जोड़ियों के लिए लागू है जहाँ रूपांतरण पूरी तरह सुरक्षित है। जैसे u8 → u16, i32 → f64, bool → i32। लेकिन u16 → u8 नहीं, क्योंकि overflow हो सकता है।

\n

इस कोड को compile करने की कोशिश करें:

\n
let big: u16 = 256;\nlet small: u8 = big.into(); // Compilation error!\n
\n

Compiler कहेगा: "the trait `From` is not implemented for `u8`"। यही सुरक्षा है - आप गलती से डेटा नहीं खो सकते।

\n\n

3. जब रूपांतरण संभव न हो: TryFrom और TryInto

\n

लेकिन अगर हम फिर भी u16 को u8 में बदलने की कोशिश करना चाहते हैं, लेकिन जाँच के साथ? तब TryFrom और TryInto काम आते हैं। ये Result लौटाते हैं, जिसे handle करना ज़रूरी है।

\n
use std::convert::TryFrom;\n\nlet big: u16 = 255;\nmatch u8::try_from(big) {\n    Ok(small) => println!("सफलता: {}", small),\n    Err(e) => println!("त्रुटि: {}", e),\n}\n// आउटपुट: सफलता: 255\n\nlet big: u16 = 256;\nmatch u8::try_from(big) {\n    Ok(small) => println!("सफलता: {}", small),\n    Err(e) => println!("त्रुटि: {}", e),\n}\n// आउटपुट: त्रुटि: TryFromIntError(())\n
\n

यही है सही Rust तरीका: आप संभावित त्रुटि को स्पष्ट रूप से handle करते हैं। अगर 100% यकीन हो तो unwrap() इस्तेमाल कर सकते हैं, लेकिन बेहतर है match का उपयोग करें।

ब्लॉग

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