परिचय: Rust कोड के साथ जादू क्यों कर सकता है?
\n\nक्या आपने कभी Rust में कोड लिखते हुए महसूस किया है कि आप दर्जनों स्ट्रक्चर के लिए एक ही कोड को बार-बार लिख रहे हैं? या आप चाहते हैं कि ट्रेट का इम्प्लीमेंटेशन अपने आप जनरेट हो जाए, बिना मैन्युअली कोड कॉपी किए? आपका स्वागत है Rust में मेटाप्रोग्रामिंग की दुनिया में — ये वो तकनीकें हैं जो आपको ऐसा कोड लिखने देती हैं जो कोड लिखता है।
\n\nRust में रनटाइम पर पूर्ण रिफ्लेक्शन (जैसे Java या Python में) नहीं है, लेकिन यह उससे कहीं अधिक शक्तिशाली और सुरक्षित चीज़ प्रदान करता है — मैक्रोज़। ये कंपाइलेशन के समय काम करते हैं, एब्सट्रैक्ट सिंटैक्स ट्री (AST) का विश्लेषण और रूपांतरण करते हैं। यह बिना परफॉरमेंस खोए बॉयलरप्लेट कोड को कम करने और ऑप्टिमाइज़ करने की अविश्वसनीय क्षमता देता है।
\n\nइस लेख में, हम मेटाप्रोग्रामिंग की उन्नत तकनीकों को समझेंगे: क्लासिक macro_rules! से लेकर पूर्ण प्रोसीजरल मैक्रोज़ तक। आप सीखेंगे कि अपने खुद के derive एट्रीब्यूट कैसे बनाएं और एट्रीब्यूट मैक्रोज़ कैसे लिखें जो कोड के अर्थ को बदल देते हैं। चलिए शुरू करते हैं!
डिक्लेरेटिव मैक्रोज़: macro_rules! — सिर्फ "टेक्स्ट रिप्लेसमेंट" नहीं
\n\nबहुत से लोग सोचते हैं कि macro_rules! एक आदिम टेक्स्ट प्रीप्रोसेसर है। वास्तव में, यह टोकन स्तर पर काम करने वाली एक शक्तिशाली पैटर्न मैचिंग प्रणाली है। यह आपको Rust के अंदर ही DSL (डोमेन-स्पेसिफिक लैंग्वेज) बनाने की अनुमति देती है।
उन्नत उदाहरण: मैक्रो के साथ बिल्डर बनाना
\n\nकल्पना करें कि आपको एक स्ट्रक्चर के लिए "बिल्डर" बनाना है। दर्जनों मेथड लिखने के बजाय, आप एक मैक्रो लिख सकते हैं:
\n\nmacro_rules! builder {\n ($struct_name:ident, { $($field:ident: $field_type:ty),* $(,)? }) => {\n struct $struct_name {\n $($field: Option<$field_type>),*\n }\n\n impl $struct_name {\n $(\n pub fn $field(mut self, value: $field_type) -> Self {\n self.$field = Some(value);\n self\n }\n )*\n\n pub fn build(self) -> Result<Self, String> {\n $(\n if self.$field.is_none() {\n return Err(format!("फ़ील्ड {} आवश्यक है", stringify!($field)));\n }\n )*\n Ok(self)\n }\n }\n };\n}\n\nbuilder!(Config, {\n host: String,\n port: u16,\n timeout: u64,\n});\n\nfn main() {\n let config = Config {\n host: None,\n port: None,\n timeout: None,\n }\n .host("localhost".to_string())\n .port(8080)\n .build()\n .unwrap();\n println!("Config तैयार: {}:{}", config.host.unwrap(), config.port.unwrap());\n}\n\n\nयह मैक्रो सिर्फ फ़ील्ड जनरेट नहीं करता, बल्कि आवश्यक फ़ील्ड की वैलिडेशन भी जोड़ता है। ध्यान दें stringify!($field) पर — यह कंपाइलेशन के समय आइडेंटिफ़ायर को स्ट्रिंग में बदल देता है। यह Rust में उन्नत मेटाप्रोग्रामिंग की एक विशिष्ट तकनीक है।
दोहराव और पैटर्न: $(...)* का उपयोग
\n\nदोहराव सिंटैक्स आपको किसी भी लंबाई के आर्गुमेंट की सूची को प्रोसेस करने देता है। ident, ty, expr और अन्य "फ्रैगमेंट्स" को मिलाकर, आप जटिल पैटर्न बना सकते हैं। उदाहरण के लिए, Display के ऑटोमैटिक इम्प्लीमेंटेशन के साथ enum बनाने का मैक्रो:
macro_rules! display_enum {\n ($enum_name:ident, { $($variant:ident => $desc:expr),* $(,)? }) => {\n enum $enum_name {\n $($variant),*\n }\n\n impl std::fmt::Display for $enum_name {\n fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n match self {\n $(Self::$variant => write!(f, "{}", $desc)),*\n }\n }\n }\n };\n}\n\ndisplay_enum!(Status, {\n Active => "status_active",\n Inactive => "status_inactive",\n Pending => "s