Rust में फ़ाइलों के बीच मैक्रोज़: मॉड्यूलर डेवलपमेंट के लिए पूर्ण ट्यूटोरियल

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

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

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

Rust में मैक्रोज़: उन्हें मॉड्यूल के साथ कैसे जोड़ें?

\n\n

क्या आपने कभी Rust में एक उपयोगी मैक्रो लिखा है, और फिर इसे पड़ोसी मॉड्यूल में उपयोग करने का प्रयास किया — और एक रहस्यमय कंपाइलर त्रुटि मिली? यदि हाँ, तो आप अकेले नहीं हैं। प्रश्न "How do I use a macro across module files?" ने Stack Overflow पर हज़ारों बार देखा गया है, और यह व्यर्थ नहीं है।

\n\n

Rust में, मैक्रोज़ मेटाप्रोग्रामिंग का एक शक्तिशाली उपकरण हैं। वे आपको फ्लाई पर कोड जनरेट करने, दोहराव से बचने और DSL (डोमेन-विशिष्ट भाषाएँ) लिखने की अनुमति देते हैं। लेकिन यहाँ एक समस्या है: मैक्रोज़ सामान्य फ़ंक्शन की तरह व्यवहार नहीं करते हैं। उनके अपने दृश्यता नियम हैं, और शुरुआती अक्सर इस पर ठोकर खाते हैं।

\n\n

इस ट्यूटोरियल में, मैं आपको मॉड्यूलर फ़ाइलों के बीच मैक्रोज़ को व्यवस्थित करने के तीन सिद्ध तरीके दिखाऊंगा। चलिए शुरू करते हैं!

\n\n

मैक्रोज़ "डिफ़ॉल्ट रूप से" काम क्यों नहीं करते?

\n\n

समाधान में गोता लगाने से पहले, आइए कारण को समझें। Rust में, फ़ंक्शन और प्रकार डिफ़ॉल्ट रूप से केवल अपने मॉड्यूल में दिखाई देते हैं (यदि pub से चिह्नित नहीं हैं)। मैक्रोज़ के साथ भी यही कहानी है, लेकिन एक बारीकियाँ हैं: मैक्रोज़ के लिए pub फ़ंक्शन की तरह काम नहीं करता है।

\n\n

एक सरल उदाहरण पर विचार करें। मान लीजिए कि हमारे पास इस संरचना वाला एक प्रोजेक्ट है:

\n\n
src/\n├── main.rs\n├── helpers/\n│   ├── mod.rs\n│   └── macros.rs\n
\n\n

macros.rs में, हमने एक मैक्रो घोषित किया:

\n\n
// src/helpers/macros.rs\nmacro_rules! greet {\n    ($name:expr) => {\n        println!("नमस्ते, {}!", $name);\n    };\n}\n
\n\n

अब हम इसे main.rs में उपयोग करना चाहते हैं:

\n\n
// src/main.rs\nmod helpers;\n\nfn main() {\n    greet!("दुनिया"); // त्रुटि! मैक्रो दिखाई नहीं दे रहा है।\n}\n
\n\n

कंपाइलर कुछ इस तरह देगा: error: macro `greet` is not imported। क्यों? क्योंकि मैक्रोज़ डिफ़ॉल्ट रूप से मॉड्यूल से निर्यात नहीं होते हैं, भले ही मॉड्यूल को pub के रूप में घोषित किया गया हो।

\n\n

विधि 1: मैक्रोज़ आयात करने के लिए #[macro_use] विशेषता

\n\n

सबसे आसान तरीका मॉड्यूल घोषणा से पहले #[macro_use] विशेषता का उपयोग करना है। यह Rust को उस मॉड्यूल से सभी मैक्रोज़ को वर्तमान दायरे में आयात करने के लिए मजबूर करता है।

\n\n

हमारे उदाहरण को ठीक करें:

\n\n
// src/main.rs\n#[macro_use]\nmod helpers;\n\nfn main() {\n    greet!("दुनिया"); // अब काम करता है!\n}\n
\n\n

लेकिन एक समस्या है: #[macro_use] मॉड्यूल से सभी मैक्रोज़ आयात करता है। यदि आपके पास बहुत सारे मैक्रोज़ हैं, तो इससे नामों में टकराव हो सकता है। इसके अलावा, आधुनिक Rust (edition 2018 से शुरू) में इस दृष्टिकोण को पुराना माना जाता है।

\n\n

यह अभी भी कहाँ उपयोगी है? छोटे प्रोजेक्ट्स में या जब आप एक प्रोटोटाइप लिख रहे हों और बिना अतिरिक्त प्रयास के कुछ मैक्रोज़ को जल्दी से कनेक्ट करना चाहते हों।

\n\n

महत्वपूर्ण बारीकियाँ: घोषणा का क्रम

\n\n

यदि आप #[macro_use] का उपयोग करते हैं, तो मैक्रोज़ मॉड्यूल घोषणा के तुरंत बाद उपलब्ध हो जाते हैं। इसका मतलब है कि निम्नलिखित कोड काम नहीं करेगा:

\n\n
// src/main.rs\nfn use_greet() {\n    greet!("परीक्षण"); // त्रुटि! मॉड्यूल अभी घोषित नहीं हुआ है।\n}\n\n#[macro_use]\nmod helpers;\n\nfn main() {\n    use_greet();\n}\n
\n\n

क्रम मायने रखता है। इसे ध्यान में रखें।

\n\n

विधि 2: #[macro_export] के साथ मैक्रोज़ का स्पष्ट निर्यात

\n\n

अधिक आधुनिक और नियंत्रित तरीका मैक्रो परिभाषा में सीधे #[macro_export] विशेषता का उपयोग करना है। यह मैक्रो को केवल मॉड्यूल के बजाय क्रेट (crate) स्तर पर उपलब्ध कराता है।

\n\n

यह इस प्रकार काम करता है:

\n\n
// src/helpers/macros.rs\n#[macro_export]\nmacro_rules! greet {\n    ($name:expr) => {\n        println!("नमस्ते, {}!", $name);\n    };\n}\n
\n\n

अब main.rs में, हम use के साथ मैक्रो को स्पष्ट रूप से आयात कर सकते हैं:

\n\n
// src/main.rs\nmod helpers;\n\nuse helpers::greet;\n\nfn main() {\n    greet!("दुनिया"); // काम करता है!\n}\n
\n\n

ध्यान दें: हम use helpers::greet का उपयोग कर रहे हैं, न कि use hel

ब्लॉग

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