ماڈیول اسباق (2/2)
حوالہ جات اور قرض لینا
زنگ میں، ملکیت کو فنکشنز کو آگے پیچھے کرنا تکلیف دہ ہو سکتا ہے۔ اسے حل کرنے کے لیے، Rust حوالہ جات (&) استعمال کرتا ہے۔
کسی قدر کا حوالہ بنانا قرض لینا کہلاتا ہے۔
ناقابل تغیر حوالہ جات
قسم یا متغیر کو & علامت کے ساتھ سابقہ لگا کر حوالہ کا اعلان کیا جاتا ہے۔ پہلے سے طے شدہ طور پر، حوالہ جات غیر متغیر ہوتے ہیں: وہ قدر کو پڑھنے کی اجازت دیتے ہیں لیکن اس میں ترمیم نہیں کرتے۔
fn main() {
let s1 = String::from("hello");
// We pass a reference to s1, not ownership
let len = calculate_length(&s1);
// s1 is still usable here!
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize { // s is a reference to a String
s.len()
} // Here, s goes out of scope, but since it doesn't own the value, nothing happensتغیر پذیر حوالہ جات
اگر آپ کو ادھار لی گئی قدر میں ترمیم کرنے کی ضرورت ہے، تو آپ کو &mut کے ساتھ میوٹ ایبل حوالہ استعمال کرنا ہوگا۔ اصل متغیر کو بھی mut کے ساتھ متغیر قرار دیا جانا چاہیے:
fn main() {
let mut s = String::from("hello");
// We pass a mutable reference
change(&mut s);
println!("{}", s); // Prints "hello, world"
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}قرض لینے کے احکام
کمپائل ٹائم میں میموری کی بدعنوانی اور ڈیٹا ریس کو روکنے کے لیے، Rust دو بنیادی اصول نافذ کرتا ہے:
- آپ کے پاس ایک ہی وقت میں کسی قدر کے لیے بہت سے متغیر حوالہ جات (
&T) ہوسکتے ہیں۔ - یا آپ کے پاس ایک وقت میں ایک قدر کے لیے بالکل ایک تغیر پذیر حوالہ (
&mut T) ہوسکتا ہے۔
آپ بالکل ایک ہی دائرہ کار میں ایک ہی قدر کے لیے ناقابل تغیر اور تغیر پذیر حوالہ جات کو ملا نہیں سکتے:
let mut s = String::from("hello");
let r1 = &s; // Valid
let r2 = &s; // Valid
// let r3 = &mut s; // COMPILATION ERROR! You cannot create &mut s if s is already borrowed as immutableحوالہ دائرہ کار اور غیر لغوی لائف ٹائم (NLL)
تاریخی طور پر، ایک حوالہ کا دائرہ اس بلاک کے اختتام تک رہتا ہے جس میں اسے بنایا گیا تھا۔ آج، رسٹ کا کمپائلر Non-Lexical Lifetimes (NLL) کی بدولت زیادہ ہوشیار ہے: ایک حوالہ کا دائرہ اس آخری سطر پر ختم ہوتا ہے جو دراصل استعمال ہوتا ہے، ضروری نہیں کہ بلاک کے آخر میں ہو۔
یہ مندرجہ ذیل کوڈ کو بالکل درست بناتا ہے:
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2); // Last use of r1 and r2. The immutable references expire here!
let r3 = &mut s; // Valid! No active immutable references exist at this pointخود ہی آزمائیں۔
& علامت کا استعمال کرتے ہوئے calculate_length فنکشن میں s1 کا ایک ناقابل تغیر حوالہ پاس کریں۔
اشارہ دکھائیں۔
سٹرنگ کا ایک ناقابل تغیر حوالہ منتقل کرنے کے لیے `/* TODO \_/`with`&s1` کو تبدیل کریں۔
3 کوششوں کے بعد حل دستیاب ہے۔
متغیر کو متغیر بنائیں (مٹ s کو دیں) اور تبدیلی کے فنکشن میں ایک متغیر حوالہ (&mut s) کو منتقل کریں تاکہ اسے سٹرنگ میں ترمیم کرنے کی اجازت دی جاسکے۔
اشارہ دکھائیں۔
`let s` اور call`change(&mut s);`کی بجائے`let mut s` استعمال کریں۔
3 کوششوں کے بعد حل دستیاب ہے۔
Declare a variable s containing String::from("Rust"). Create two distinct immutable references r1 and r2 to s, and finally print both references separated by a space using the println! macro.
اشارہ دکھائیں۔
Assign `let r1 = &s;` and `let r2 = &s;` to obtain two immutable references, then print them with `println!("{} {}", r1, r2);`.
3 کوششوں کے بعد حل دستیاب ہے۔