နားလည်ထားရမယ့် အချက်
Slice ဆိုတာ collection (string, array) တစ်ခုလုံးကို ownership မယူဘဲ ဒီ collection ရဲ့ contiguous portion တစ်ခုကို ရည်ညွှန်းတဲ့ reference အမျိုးအစားတစ်ခုပါ—`&[1, 2, 3]` array slice တစ်ခုက array တစ်ခုလုံး (သို့) portion တစ်ခုကို "view" လုပ်ခွင့်ပေးပြီး ကိုယ်ပိုင် data ကို ဘယ်တော့မှ ကိုယ်တိုင် သိမ်းမထားပါဘူး။ String slice (`&str`) ကတော့ ဒီ concept ရဲ့ special case ဖြစ်ပြီး `String` ရဲ့ owned, growable, heap-allocated data ကို ရည်ညွှန်းတဲ့ borrowed view တစ်ခု ဖြစ်ပါတယ်—string literal (`"hello"`) တွေကလည်း compile time constant အဖြစ် binary ထဲ embed ထားလို့ type အနေနဲ့ `&str` ပဲ ဖြစ်ပါတယ်။ `String` ကတော့ owned, mutable, heap-allocated ဖြစ်ပြီး runtime မှာ size ကြီးလာနိုင်တာကြောင့် `push_str`, `+` operator စတာတွေနဲ့ modify လုပ်နိုင်ပေမယ့် `&str` ကတော့ borrowed view ဖြစ်တဲ့အတွက် immutable ဖြစ်ပါတယ်။ Function parameter type ကို `&str` အနေနဲ့ ရေးထားရင် `String` (`&my_string`) နှင့် `&str` literal နှစ်မျိုးလုံးကို accept လုပ်နိုင်လို့ ပိုပြီး flexible ဖြစ်ပါတယ်—ဒါကို Lesson 7 ရဲ့ "borrow-first design" ရဲ့ practical example တစ်ခုအနေနဲ့ တွေးလို့ရပါတယ်။ Slice ရဲ့ safety guarantee အတွက် အရေးကြီးတာက—slice ကို hold လုပ်နေသရွေ့ underlying data ကို mutate မလုပ်ရအောင် borrow checker ကထိန်းချုပ်ပေးလို့ slice ကို ကိုင်ထားပြီး original data ပြောင်းလိုက်ရင် ဖြစ်တတ်တဲ့ classic C-style "dangling slice/pointer" bug ကို compile time မှာပင် ကာကွယ်ပေးပါတယ်။
လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်
Content analyzer ရဲ့ function တွေကို `fn first_paragraph(text: &str) -> &str` လို ရေးမယ်—input parameter (`&str`) နှင့် return value (`&str`) နှစ်ခုစလုံးက `String` (`&lesson_body`) ကို ခေါ်လည်း string literal ကို ခေါ်လည်း လုပ်လို့ရပါတယ်။ Lesson body ရဲ့ ပထမဆုံး 100 character ကို preview text အဖြစ် ထုတ်ချင်ရင် `&text[..100]` slice syntax ကို သုံးမယ်—ဒီ slice ကို hold ထားသရွေ့ underlying `String` ကို ဆက်ပြောင်းလို့ မရပါဘူး—borrow checker ကို ကိုယ်တိုင် ခံစားရမည့် direct example တစ်ခုပါ။ Tags ကို `Vec<String>` အဖြစ် သိမ်းပေမယ့် tags ကို filter/search လုပ်တဲ့ function တွေရဲ့ parameter ကိုတော့ `&[String]` (slice) အနေနဲ့ ရေးမယ်—caller ဘက်က `Vec` တစ်ခုလုံးကို move ပေးစရာ မလိုတော့ပါ။
အတူတူ စမ်းရေးကြည့်မယ်
fn first_paragraph(text: &str) -> &str {
match text.find("\n\n") {
Some(pos) => &text[..pos],
None => text,
}
}
fn main() {
let owned = String::from("Ownership basics.\n\nRust prevents data races.");
println!("{}", first_paragraph(&owned));
println!("{}", first_paragraph("A literal works too.\n\nSecond part."));
}"Ownership basics." နှင့် "A literal works too." ကို print ထုတ်နိုင်မည်—function တစ်ခုတည်းက `String` reference နှင့် literal နှစ်မျိုးလုံး လက်ခံနိုင်ကြောင်း သက်သေပြမည်။၅ မိနစ် စမ်းကြည့်
`fn last_word(text: &str) -> &str` function ရေးပါ—text ရဲ့ နောက်ဆုံး word ကို slice အနေနဲ့ ပြန်ပေးရမည် (whitespace ဖြင့်ပိုင်း)—`String` variable တစ်ခု နှင့် string literal တစ်ခု နှစ်မျိုးလုံးနှင့် test ကြည့်ပါ။
သတိလေးတစ်ချက်
Function parameter type ကို `&String` (specific) အနေနဲ့ ရေးထားခြင်း—string literal ကို ဒီ function ဆီ တိုက်ရိုက် pass လို့ မရတော့ဘဲ `&str` ရေးရင် ရနိုင်မယ့် flexibility ကို ဆုံးရှုံးနေခြင်း။
String slice ကို byte index (`&text[..5]`) ဖြင့် ဖြတ်ကြည့်တဲ့အခါ multi-byte UTF-8 character (ဥပမာ မြန်မာစာလုံး) ရဲ့ boundary အလယ်ကနေ ဖြတ်မိပြီး runtime panic ဖြစ်ခြင်း—character boundary ကို သတိထားရပါမယ်။