Rust में फंक्शन को आर्गुमेंट के रूप में: फंक्शन पास करने के 3 तरीके

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

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

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

Rust में फंक्शन को आर्गुमेंट के रूप में: शुरुआत से विशेषज्ञ तक

\n\n

क्या आपने कभी Python या JavaScript में लिखा है और आसानी से एक फंक्शन को दूसरे फंक्शन में पास किया है? और फिर Rust पर आए और एक सामान्य जगह पर अटक गए? परिचित लगता है। सवाल "How do you pass a Rust function as a parameter?" — Stack Overflow पर सबसे लोकप्रिय में से एक है। और यह सही भी है: Rust का टाइप सिस्टम और स्वामित्व कई जटिलताएँ जोड़ता है, लेकिन नई संभावनाएँ भी खोलता है।

\n\n

इस लेख में, हम तीन मुख्य दृष्टिकोणों पर चर्चा करेंगे: फंक्शन पॉइंटर्स (fn), क्लोज़र्स (closures) और ट्रेट्स। आप जानेंगे कि कब किसका उपयोग करना है, और Rust में कार्यात्मक शैली से डरना छोड़ देंगे।

\n\n

यह क्यों महत्वपूर्ण है?

\n

फंक्शन को पैरामीटर के रूप में पास करने की क्षमता केवल एक अकादमिक चाल नहीं है। यह इसके लिए आधार है:

\n
    \n
  • लचीली और पुन: प्रयोज्य लाइब्रेरी बनाना (उदाहरण के लिए, इटरेटर, इवेंट हैंडलर);
  • \n
  • "स्ट्रैटेजी" और "ऑब्ज़र्वर" पैटर्न को लागू करना;
  • \n
  • बहुत सारे if-else के बिना संक्षिप्त और अभिव्यंजक कोड लिखना।
  • \n
\n

Rust में, डायनामिक भाषाओं के विपरीत, कंपाइलर टाइप और लाइफटाइम की सख्ती से जाँच करता है। इसलिए, आपको स्पष्ट रूप से समझना होगा कि आप क्या पास कर रहे हैं: केवल एक फंक्शन का पता, संदर्भ को कैप्चर करने वाला क्लोज़र, या कुछ अधिक जटिल।

\n\n

दृष्टिकोण 1: फंक्शन पॉइंटर — fn

\n

सबसे सरल और सीधा तरीका। यदि आपका फंक्शन बाहरी वातावरण से वेरिएबल कैप्चर नहीं करता है (यह "शुद्ध" है), तो आप fn टाइप का उपयोग कर सकते हैं। ध्यान दें: fn एक टाइप है, जबकि Fn, FnMut, FnOnce ट्रेट्स हैं। इन्हें भ्रमित न करें!

\n\n
fn add_one(x: i32) -> i32 {\n    x + 1\n}\n\n// फंक्शन जो दूसरे फंक्शन को स्वीकार करता है\nfn apply_twice(f: fn(i32) -> i32, value: i32) -> i32 {\n    f(f(value))\n}\n\nfn main() {\n    let result = apply_twice(add_one, 5);\n    println!("परिणाम: {}", result); // 7\n}
\n\n

कब उपयोग करें? जब फंक्शन कंपाइल टाइम पर ज्ञात हो, वेरिएबल कैप्चर न करता हो, और आपको क्लोज़र्स के प्रदर्शन की आवश्यकता न हो। फंक्शन पॉइंटर्स एक zero-cost abstraction हैं, उन्हें एलोकेशन की आवश्यकता नहीं होती।

\n\n

fn की सीमाएँ

\n

मुख्य नुकसान: आप एक ऐसा क्लोज़र पास नहीं कर सकते जो वेरिएबल कैप्चर करता हो। निम्नलिखित कोड कंपाइल नहीं होगा:

\n\n
fn main() {\n    let y = 10;\n    // क्लोज़र y को कैप्चर करता है\n    let closure = |x: i32| -> i32 { x + y };\n    // त्रुटि! expected fn item, found closure\n    // let result = apply_twice(closure, 5);\n}
\n\n

इसके लिए Fn, FnMut, FnOnce ट्रेट्स की आवश्यकता होती है।

\n\n

दृष्टिकोण 2: क्लोज़र्स और ट्रेट्स Fn, FnMut, FnOnce

\n

Rust एक सिस्टम भाषा है, और इसे पता होना चाहिए कि मेमोरी के साथ क्या हो रहा है। क्लोज़र्स वेरिएबल को तीन तरीकों से कैप्चर कर सकते हैं:

\n
    \n
  • रेफरेंस द्वारा (&T) — ट्रेट Fn। इसे जितनी बार चाहें कॉल किया जा सकता है, कैप्चर किए गए डेटा को बदले बिना।
  • \n
  • म्यूटेबल रेफरेंस द्वारा (&mut T) — ट्रेट FnMut। इसे कई बार कॉल किया जा सकता है, लेकिन डेटा बदल सकता है।
  • \n
  • वैल्यू द्वारा (T) — ट्रेट FnOnce। इसे केवल एक बार कॉल किया जा सकता है, उसके बाद क्लोज़र "खपत" हो जाता है।
  • \n
\n\n

Fn के साथ उदाहरण

\n
fn apply_twice_fn<F>(f: F, value: i32) -> i32\nwhere\n    F: Fn(i32) -> i32,\n{\n    f(f(value))\n}\n\nfn main() {\n    let y = 10;\n    let closure = |x| x + y; // y को रेफरेंस द्वारा कैप्चर करता है\n    let result = apply_twice_fn(closure, 5);\n    println!("Fn: {}", result); // 25\n}
\n\n

FnMut के साथ उदाहरण

\n
fn apply_twice_mut<F>(mut f: F, value: i32) -> i32\nwhere\n    F: FnMut(i32) -> i32,\n{\n    f(f(value))\n}\n\nfn main() {\n    let mut counter = 0;\n    let mut closure = |x: i32| -> i32 {\n                

ब्लॉग

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