နားလည်ထားရမယ့် အချက်
Lesson 6 ရဲ့ ownership move ကို ရှောင်ချင်ရင် reference (`&`) ကို သုံးပြီး value ကို "borrow" လုပ်နိုင်ပါတယ်—function တစ်ခုဆီ `&content` ကို pass လိုက်ရင် ownership ဟာ caller ဆီမှာပဲ ကျန်နေပြီး function က ဒီ value ကို temporarily ကြည့်ခွင့်ရရုံသာ ရပါတယ်—function ပြီးသွားရင် borrow ကလည်း ပြီးဆုံးသွားပါတယ်။ Reference က default အနေနဲ့ immutable (`&T`) ဖြစ်ပြီး value ကို ပြောင်းချင်ရင် mutable reference (`&mut T`) ကို explicit သတ်မှတ်ပေးရပါတယ်။ Borrow checker ရဲ့ core rule ကတော့—value တစ်ခုအတွက် scope တူတူထဲမှာ mutable reference တစ်ခုတည်း OR immutable reference အများအပြား ရှိနိုင်ပေမယ့် နှစ်ခုစလုံး တစ်ပြိုင်နက် မဖြစ်ရ ဆိုတဲ့ constraint ပါ—ဒါက read-write conflict (တစ်ယောက်က data ဖတ်နေချိန် တစ်ယောက်က ပြောင်းနေခြင်း) ကို compile time မှာ လုံးဝဖြစ်မလာအောင် ကာကွယ်ပေးတာဖြစ်ပါတယ်။ ဒီ rule ကို library book တစ်အုပ်နဲ့ တွေးလို့ရပါတယ်—တစ်ယောက်တည်းက book ထဲမှာ pencil ဖြင့် edit လုပ်နေချိန် တခြားသူတွေ ဖတ်ခွင့်ပေးလို့ မရဘူး (data corruption ဖြစ်နိုင်လို့)—ဒါပေမယ့် ဘယ်သူမှ edit မလုပ်နေရင်တော့ လူများစွာ တစ်ပြိုင်နက်ဖတ်ဖို့ လုံးဝ safe ပါတယ်။ ဒီ rule ကို compile time မှာ enforce လုပ်လို့ concurrency code (Lesson 18) ထဲမှာ ဒီ constraint ကို thread များကြားတောင် extend လုပ်ပေးလို့ data race ဆိုတာ compiler error တစ်ခုပဲ ဖြစ်လာစေပါတယ်—runtime bug မဟုတ်တော့ပါဘူး။
လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်
Content analyzer ရဲ့ `count_words` function ကို `fn count_words(text: &str) -> u32` လို ownership မယူဘဲ borrow ချင်ရေးမယ်—caller ရဲ့ original `String` ကို ဒီ function ကို ခေါ်ပြီးနောက်ပါ ဆက်သုံးနိုင်မှာဖြစ်ပါတယ်။ Lesson stats vector ကို in-place update ချင်ရင် `fn update_stats(stats: &mut Vec<LessonStat>) { ... }` လို mutable reference ကို pass မယ်—ဒီအချိန်မှာ caller ဘက်က ဒီ vector ရဲ့ တခြား reference (immutable ဖြစ်စေ mutable ဖြစ်စေ) တစ်ခုမှ တစ်ပြိုင်နက် active မဖြစ်စေရပါ—compiler ကလည်း ဒီ constraint ကို automatically enforce ပေးမှာပါ။ Files array တစ်ခုကို ဖတ်ရုံသာ လိုအပ်တဲ့ report-generation function တွေအတွက် `&Vec<LessonStat>` (immutable borrow) ကို consistently သုံးမယ်—function များစွာက တစ်ပြိုင်နက် read လုပ်နိုင်ဖို့ပါ။
အတူတူ စမ်းရေးကြည့်မယ်
fn count_words(text: &str) -> u32 {
text.split_whitespace().count() as u32
}
fn append_tag(tags: &mut Vec<String>, tag: &str) {
tags.push(tag.to_string());
}
fn main() {
let content = String::from("Rust references and borrowing");
let count = count_words(&content);
println!("{content} -> {count} words"); // content still usable
let mut tags = vec![String::from("rust")];
append_tag(&mut tags, "ownership");
println!("{tags:?}");
}"Rust references and borrowing -> 4 words" နှင့် `["rust", "ownership"]` ကို print ထုတ်နိုင်မည်။၅ မိနစ် စမ်းကြည့်
`Vec<String>` variable တစ်ခု ဖန်တီးပြီး ဒီ vector ကို immutable reference နှစ်ခု (`&v`) တစ်ပြိုင်နက် ယူကြည့်ပါ (allowed)—ပြီးရင် immutable reference တစ်ခု active နေချိန် mutable reference (`&mut v`) ကို ထပ်ယူကြည့်ပါ—compile error message ကို ဖတ်ကြည့်ပါ။
သတိလေးတစ်ချက်
Value တစ်ခုကို scope တူတူထဲမှာ mutable reference နှင့် immutable reference တစ်ပြိုင်နက်ယူကြိုးစားခြင်း—borrow checker က "cannot borrow as mutable because it is also borrowed as immutable" error ဖြင့် ချက်ချင်း block ပေးပါမည်။
Function parameter ကို owned type (`String`) အဖြစ်ချည်း ရေးထားခြင်းကြောင့် caller ဘက်က borrow (`&str`) နဲ့ လုံလောက်တဲ့ function ကို ownership move ခိုင်းနေခြင်း—function ကို borrow-first design ဖြင့် ရေးရင် caller flexibility ပိုရလာပါတယ်။
The Rust Programming Language — References and Borrowing — Rust