Rust में किसी नाम को कोई वैल्यू असाइन करने को बाइंडिंग कहा जाता है। जब तक किसी बाइंडिंग को mut कीवर्ड के साथ घोषित न किया जाए, वह अपरिवर्तनीय रहती है। चूँकि Rust स्टैटिक टाइप वाली भाषा है, इसलिए हर बाइंडिंग का एक टाइप होता है जो कंपाइल के समय ही ज्ञात होता है।
बाइंडिंग आम तौर पर let कीवर्ड से बनाई जाती हैं। ज़्यादातर बाइंडिंग के लिए उसका टाइप लिखना ज़रूरी नहीं होता, क्योंकि Rust का टाइप इनफरेंस आम तौर पर उनकी वैल्यू के आधार पर टाइप का अनुमान लगा लेता है। एक बाइंडिंग ऐसी दिखती है:
// Automatically inferred type
let fingers = 10;
फंक्शन आइटम होते हैं। जहाँ बाइंडिंग आम तौर पर किसी एक खास वैल्यू को दर्शाती हैं, वहीं आइटम कोड को व्यवस्थित करने की एक इकाई को दर्शाते हैं, जो आम तौर पर कोई फंक्शन या मॉड्यूल होता है और प्रोग्राम के पूरे जीवनकाल तक उपलब्ध रहता है। एक फंक्शन अपने आप अपने अंतिम एक्सप्रेशन का परिणाम लौटाता है। किसी फंक्शन में 0 या उससे अधिक पैरामीटर हो सकते हैं, जो ऐसी बाइंडिंग होती हैं जिनका जीवनकाल फंक्शन कॉल तक ही रहता है।
फंक्शन के लिए टाइप इनफरेंस सैद्धांतिक रूप से संभव तो है, लेकिन भाषा के डिज़ाइन में इसे जानबूझकर बंद रखा गया है। इसका मतलब है कि कोड लिखते समय आपको यह बताने में थोड़ा अधिक समय लगता है कि फंक्शन के इनपुट और आउटपुट टाइप ठीक-ठीक क्या हैं, लेकिन कोड पढ़ते समय आपका समय बचता है, क्योंकि सारे इनपुट और आउटपुट टाइप साफ़-साफ़ लिखे होते हैं।
fn add(x: i32, y: i32) -> i32 {
x + y
}
किसी फंक्शन को कॉल करने के लिए उसका नाम लिखा जाता है और उसके बाद ब्रैकेट लगाए जाते हैं। अगर फंक्शन को पैरामीटर चाहिए, तो ब्रैकेट के अंदर हर पैरामीटर के लिए एक आर्गुमेंट देना होता है।
let five = add(2, 3);
अगर किसी बाइंडिंग का टाइप अनुमान से तय न हो पाए, तो कंपाइलर एक एरर बताता है। इसे ठीक करने के लिए बाइंडिंग में उसका टाइप साफ़-साफ़ लिखकर बताइए।
// Explicit type annotation
let fingers: i32 = 10;
Rust में आइटम का इस्तेमाल उन्हें बनाने से पहले या बाद में कभी भी किया जा सकता है, क्योंकि उनका जीवनकाल स्टैटिक होता है। बाइंडिंग की बात अलग है: उनका इस्तेमाल उन्हें बनाने के बाद ही किया जा सकता है। किसी बाइंडिंग को उसके बनने से पहले इस्तेमाल करने पर कंपाइल एरर आती है।
fn main() {
// `fn add` hasn't yet been defined, but that's perfectly ok
dbg!(add(3, 4));
}
fn add(x: i32, y: i32) -> i32 {
x + y
}
// this won't compile; `a` is used before its binding is defined
let b = a;
let a = x + y;
Rust स्कोप तय करने के लिए कर्ली ब्रैकेट ({}) का इस्तेमाल करता है। किसी स्कोप के अंदर बनाई गई बाइंडिंग उससे बाहर नहीं निकल सकती।
let a = 1;
dbg!(a); // 1
{
// Here, we re-bind `a` to a new value, which is still immutable.
// This technique is called _shadowing_. The new binding is constrained to
// this anonymous scope. Outside this scope, the previous binding still
// applies.
let a = 2;
let b = 3;
dbg!(a, b); // 2, 3
}
// can't use `b` anymore because it is out of scope
// dbg!(b);
// The shadowed `a` in the inner scope above has fallen out of scope,
// leaving us with our original binding.
dbg!(a); // 1
Rust के आइटम अक्सर मॉड्यूल में व्यवस्थित किए जाते हैं। हर क्रेट अपने आप में एक मॉड्यूल होता है, लेकिन वह अपने अंदर किसी भी गहराई तक सब-मॉड्यूल बना सकता है। एक मॉड्यूल जुड़े हुए काम को एक साथ रखता है, और उसे mod कीवर्ड से बनाया जाता है।
mod calc_i32 {
fn add(a: i32, b: i32) -> i32 { a + b }
fn sub(a: i32, b: i32) -> i32 { a - b }
fn mul(a: i32, b: i32) -> i32 { a * b }
fn div(a: i32, b: i32) -> i32 { a / b }
}
Rust दो तरह के कमेंट का समर्थन करता है। // कीवर्ड सिंगल-लाइन कमेंट दिखाता है; इस कीवर्ड के बाद लाइन के अंत तक जो कुछ भी लिखा हो, उसे नज़रअंदाज़ कर दिया जाता है। /* और */ कीवर्ड मल्टी-लाइन कमेंट दिखाते हैं; इन दोनों कीवर्ड के बीच लिखी हर चीज़ नज़रअंदाज़ कर दी जाती है। सिंगल-लाइन कमेंट को प्राथमिकता देना अच्छा और स्वाभाविक तरीका माना जाता है।
Rust डॉक-कमेंट का भी समर्थन करता है, जो cargo doc से बने डॉक्युमेंटेशन में दिखते हैं। आउटर डॉक कमेंट /// कीवर्ड से बनते हैं, और ये // कीवर्ड की तरह ही काम करते हैं। ये अपने बाद आने वाले आइटम पर लागू होते हैं, जैसे किसी फंक्शन पर:
/// The `add` function produces the sum of its arguments.
fn add(x: i32, y: i32) -> i32 { x + y }
इनर डॉक कमेंट //! कीवर्ड से बनते हैं, और ये // कीवर्ड की तरह ही काम करते हैं। ये उस आइटम पर लागू होते हैं जिसके अंदर ये लिखे गए हैं, जैसे किसी मॉड्यूल पर:
mod my_cool_module {
//! This module is the bee's knees.
}
डॉक कमेंट किसी भी लंबाई के हो सकते हैं और उनमें Markdown भी हो सकता है, जिसे तैयार होने वाले डॉक्युमेंटेशन में दिखाया जाता है।
इस अभ्यास में आप अपनी पसंदीदा कुकबुक से एक शानदार लसान्या पकाने में मदद करने के लिए कुछ कोड लिखेंगे।
आपके सामने चार काम हैं, जो सब लसान्या पकाने में लगने वाले समय से जुड़े हैं।
यह जाँचने के लिए कि लसान्या को ओवन में कितने मिनट रहना चाहिए, expected_minutes_in_oven बाइंडिंग बनाइए। कुकबुक के अनुसार ओवन में लगने वाला अपेक्षित समय 40 मिनट है:
expected_minutes_in_oven()
// Returns: 40
remaining_minutes_in_oven फंक्शन बनाइए। यह फंक्शन एक पैरामीटर लेता है: लसान्या वास्तव में ओवन में जितने मिनट रही है। पिछले काम में तय अपेक्षित ओवन समय के आधार पर यह लौटाता है कि लसान्या को ओवन में अभी कितने मिनट और रहना है।
remaining_minutes_in_oven(30)
// Returns: 10
preparation_time_in_minutes फंक्शन बनाइए। यह फंक्शन एक पैरामीटर लेता है: लसान्या में आपने जितनी परतें लगाई हैं उनकी संख्या। यह मानते हुए कि हर परत को तैयार करने में आपको 2 मिनट लगते हैं, यह लौटाता है कि लसान्या तैयार करने में आपने कितने मिनट लगाए।
preparation_time_in_minutes(2)
// Returns: 4
elapsed_time_in_minutes फंक्शन बनाइए। यह फंक्शन दो पैरामीटर लेता है: पहला पैरामीटर लसान्या में आपने जितनी परतें लगाई हैं उनकी संख्या है, और दूसरा पैरामीटर लसान्या के ओवन में रहने के मिनटों की संख्या है। फंक्शन को लौटाना चाहिए कि आपने लसान्या पकाने में कितने मिनट काम किया, यानी तैयारी के मिनटों और इस समय लसान्या के ओवन में बिताए गए मिनटों का जोड़।
elapsed_time_in_minutes(3, 20)
// Returns: 26