Rust में DSL: वास्तविक समस्याओं के लिए अपनी भाषा लिखें

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

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

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

Rust डेवलपर को अपनी भाषा की आवश्यकता क्यों? DSL की दुनिया में गोता

\n\n

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

\n\n

Rust DSL बनाने के लिए एक आदर्श वातावरण है। इसकी मैक्रो प्रणाली, शक्तिशाली प्रकार अनुमान और शून्य-लागत अमूर्तता आपको ऐसी भाषाएँ बनाने की अनुमति देती है जो प्रदर्शन में हस्तलिखित कोड से कम नहीं होती हैं। इस लेख में, हम यह समझेंगे कि Rust को अपनी भाषाओं के निर्माण खिलौने में कैसे बदलें, और दिखाएंगे कि यह आपके लिए क्यों उपयोगी हो सकता है।

\n\n

DSL क्या है और Rust में इसकी आवश्यकता क्यों?

\n\n

DSL (डोमेन-विशिष्ट भाषा) एक ऐसी भाषा है जो किसी विशिष्ट डोमेन में समस्याओं को हल करने के लिए बनाई गई है। सामान्य प्रोग्रामिंग भाषा के विपरीत, DSL एक संकीर्ण क्षेत्र में अभिव्यक्ति के लिए सार्वभौमिकता का त्याग करता है। Rust पारिस्थितिकी तंत्र में दो मुख्य दृष्टिकोण हैं:

\n\n
    \n
  • आंतरिक (एम्बेडेड) DSL — मैक्रोज़ और विधि श्रृंखलाओं का उपयोग करके Rust सिंटैक्स के ऊपर बनाए जाते हैं। उदाहरण: कमांड-लाइन आर्गुमेंट पार्सिंग के लिए लाइब्रेरी clap।
  • \n
  • बाहरी (एक्सटर्नल) DSL — एक अलग सिंटैक्स जो रनटाइम पर पार्स किया जाता है। उदाहरण: regex या sqlx।
  • \n
\n\n

Rust में DSL का विकास विशेष रूप से प्रासंगिक है:

\n
    \n
  • कॉन्फ़िगरेशन फ़ाइलों के लिए (बाहरी DSL के रूप में YAML/TOML)
  • \n
  • गेम इंजन के लिए (NPC व्यवहार का वर्णन)
  • \n
  • परीक्षण फ्रेमवर्क के लिए (परिदृश्यों के लिए अपना सिंटैक्स)
  • \n
  • सुरक्षा और लचीलेपन के बीच संतुलन के लिए
  • \n
\n\n

Rust में आंतरिक DSL बनाना: मैक्रोज़ और श्रृंखलाएँ

\n\n

चलिए सरल से शुरू करते हैं — HTTP अनुरोधों का वर्णन करने के लिए एक आंतरिक DSL। यह लिखने के बजाय:

\n\n
let mut req = Request::new(Method::GET);\nreq.set_url("https://api.example.com/data");\nreq.add_header("Authorization", "Bearer token");\nreq.add_header("Content-Type", "application/json");\n
\n\n

हम एक संक्षिप्त सिंटैक्स चाहते हैं:

\n\n
let req = request! {\n    GET "https://api.example.com/data"\n    headers {\n        "Authorization": "Bearer token",\n        "Content-Type": "application/json"\n    }\n};\n
\n\n

हम इसे Rust मैक्रोज़ का उपयोग करके लागू करते हैं — आंतरिक DSL बनाने का सबसे शक्तिशाली उपकरण:

\n\n
macro_rules! request {\n    ($method:ident $url:expr) => {\n        Request::new(stringify!($method).parse().unwrap(), $url)\n    };\n    ($method:ident $url:expr, headers { $($key:expr => $value:expr),* $(,)? }) => {\n        {\n            let mut req = Request::new(stringify!($method).parse().unwrap(), $url);\n            $(\n                req.add_header($key, $value);\n            )*\n            req\n        }\n    };\n}\n
\n\n

यह दृष्टिकोण Rust पर डोमेन-विशिष्ट भाषा का एक उत्कृष्ट उदाहरण है: हम एक नया सिंटैक्स नहीं बनाते, बल्कि मौजूदा को पुनर्परिभाषित करते हैं, कोड को अधिक पठनीय बनाते हैं। ध्यान दें: मैक्रो संकलन चरण पर सामान्य Rust कोड उत्पन्न करता है, इसलिए प्रकार की त्रुटियाँ चलाने से पहले पकड़ी जाती हैं।

\n\n

उन्नत आंतरिक DSL: बिल्डर पैटर्न

\n\n

मैक्रोज़ ही एकमात्र तरीका नहीं हैं। अक्सर Rust में DSL बनाने के लिए विधि श्रृंखलाओं के साथ बिल्डर पैटर्न का उपयोग किया जाता है। SQL क्वेरी के लिए DSL का उदाहरण देखें:

\n\n
let query = Query::select()\n    .from("users")\n    .where_clause("age > ?")\n    .bind(18)\n    .order_by("name")\n    .build();\n
\n\n

ऐसे DSL का कार्यान्वयन सरल और सुरुचिपूर्ण है:

\n\n
struct QueryBuilder {\n    select: Vec<String>,\n    from: String,\n    condition: Option<String>,\n    order: Option<String>,\n}\n\                

ब्लॉग

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