परिचय: Generics क्या हैं और Rust में इनकी आवश्यकता क्यों है?
Rust एक सिस्टम प्रोग्रामिंग भाषा है, जो अपनी सुरक्षा, प्रदर्शन और सख्त प्रकार प्रणाली के लिए प्रसिद्ध है। लचीला और पुन: प्रयोज्य कोड लिखने में सक्षम बनाने वाले प्रमुख उपकरणों में से एक हैं Generics (सामान्यीकृत प्रकार)।
Generics आपको फ़ंक्शन, संरचनाएं, एनुम और विधियाँ बनाने की अनुमति देते हैं जो कोड को दोहराए बिना विभिन्न डेटा प्रकारों के साथ काम कर सकते हैं। i32, f64 या String के लिए अलग-अलग फ़ंक्शन लिखने के बजाय, आप एक सामान्यीकृत संस्करण लिखते हैं।
उदाहरण के लिए, Generics के बिना, आपको तीन अलग-अलग प्रकारों को सॉर्ट करने के लिए तीन अलग-अलग फ़ंक्शन बनाने होंगे। Generics के साथ, केवल एक। यह न केवल कोड की मात्रा को कम करता है, बल्कि इसकी विश्वसनीयता भी बढ़ाता है: कंपाइलर रनटाइम के बजाय संकलन चरण में प्रकारों की शुद्धता की जाँच करता है।
मुख्य भाग: Rust में Generics कैसे काम करते हैं
1. सामान्यीकृत फ़ंक्शन: एक बार लिखें - किसी भी प्रकार के लिए उपयोग करें
Generics से परिचित होने का सबसे आसान तरीका सामान्यीकृत फ़ंक्शन है। कल्पना करें कि आपको एक फ़ंक्शन लिखना है जो दो मानों में से सबसे बड़ा लौटाता है। इसे प्रत्येक प्रकार के लिए अलग-अलग लिखने के बजाय, हम सामान्यीकरण का उपयोग करते हैं:
fn largest<T: PartialOrd>(list: &[T]) -> &T { let mut largest = &list[0]; for item in list { if item > largest { largest = item; } } largest}
fn main() { let numbers = vec![34, 50, 25, 100, 65]; let result = largest(&numbers); println!("सबसे बड़ी संख्या: {}", result);
let chars = vec!['y', 'm', 'a', 'q']; let result = largest(&chars); println!("सबसे बड़ा वर्ण: {}", result);}यहाँ <T: PartialOrd> का अर्थ है कि फ़ंक्शन किसी भी प्रकार T के साथ काम करता है जो तुलना का समर्थन करता है (ट्रेट PartialOrd)। इसे ट्रेट बाउंड कहा जाता है - एक महत्वपूर्ण अवधारणा जिस पर आगे चर्चा की जाएगी।
2. सामान्यीकृत संरचनाएं और एनुम: डेटा परिभाषा में लचीलापन
Generics न केवल फ़ंक्शन पर, बल्कि डेटा संरचनाओं पर भी लागू होते हैं। एक उत्कृष्ट उदाहरण Point संरचना है, जो विभिन्न प्रकारों के निर्देशांक संग्रहीत कर सकती है:
struct Point<T> { x: T, y: T,}
fn main() { let integer_point = Point { x: 5, y: 10 }; let float_point = Point { x: 1.0, y: 4.0 }; // let wont_work = Point { x: 5, y: 4.0 }; // त्रुटि! अलग-अलग प्रकार}यदि आप चाहते हैं कि x और y अलग-अलग प्रकार के हो सकें, तो एकाधिक सामान्यीकरण पैरामीटर का उपयोग करें:
struct Point<T, U> { x: T, y: U,}
fn main() { let mixed_point = Point { x: 5, y: 4.0 }; // काम करता है!}यही बात एनुम के लिए भी काम करती है। सबसे प्रसिद्ध उदाहरण Option<T> और Result<T, E> हैं, जो सामान्यीकृत हैं:
enum Option<T> { Some(T), None,}
enum Result<T, E> { Ok(T), Err(E),}3. सामान्यीकृत संरचनाओं में विधियाँ: तर्क जोड़ना
आप impl ब्लॉक का उपयोग करके सामान्यीकृत संरचनाओं के लिए विधियाँ परिभाषित कर सकते हैं। साथ ही, आप ऐसी विधियाँ बना सकते हैं जो केवल विशिष्ट प्रकारों के लिए काम करती हैं:
struct Point<T> { x: T, y: T,}
// सभी प्रकार T के लिए विधियाँimpl<T> Point<T> { fn x(&self) -> &T { &self.x }}
// केवल f64 प्रकार के लिए विधिimpl Point<f64> { fn distance_from_origin(&self) -> f64 { (self.x.powi(2) + self.y.powi(2)).sqrt() }}
fn main() { let p = Point { x: 3.0, y: 4.0 }; println!("p.x = {}", p.x()); println!("मूल बिंदु से दूरी: {}", p.distance_