Agarda biz reference olayotganda, olingan ma’lumotni o’zgartirishni hoxlasak, unda o’zgaruvchan reference olishimiz kerak bo’ladi. Buning uchun “&mut” dan foydalanishimiz kerak.
fn main() {
let mut my_number = 8; // o'zgaruvchi elon qilinayotganda mut qo'shish kerak
let num_ref = &mut my_number;
}
Xo’sh tepadagi ikkita o’zgaruvchining ma’lumot turlari qanday ? “my_number” i32 bo’lsa , “num_ref” esa bizda &mut i32, ya’ni o’zgaruvchan reference deb ataladi.
Agar “my_number” ga 10 qiymat qo’shmoqchi bo’lsak, biz uni “num_ref” orqali ham amalga oshirsak bo’ladi, lekin “num_ref +=10” qilib emas. Sababi, num_ref dagi qiymat &i32 shaklida bo’ladi. Bu degani haqiqiy qiymatga ko’rsatgich sifatida tushunishimiz mumkin. Shuning uchun ham biz haqiqiy qiymatni olishimiz kerak va bunda yulduzcha(*) operatoridan foydalanamiz. Agarda biz reference qilingan o’zgaruvchining oldiga (*) bilan yozsak, bizga haqiqiy qiymatni olib beradi.
fn main() {
let mut my_number = 8;
let num_ref = &mut my_number;
*num_ref += 10; // * ishlatish kerak qiymat o'zgartirishga
println!("{}", my_number);
let second_number = 800;
let triple_reference = &&&second_number;
println!("Second_number = triple_reference? {}", second_number == ***triple_reference);
}
Natija:
18
Second_number = triple_reference? true
Rust da o’zgaruvchan va o’zgarmas reference lar uchun ikkita qoida mavjud. Ular juda muhim va eslab qolish uchun oson.
- Qoida 1: Agar bizda o’zgarmas reference(&) bo’lsa, biz istalgancha reference olishimiz mumkin.
- Qoida 2: Agar bizda o’zgaruvchan reference(&mut) bo’lsa, biz faqatgina bitta reference olishimiz mumkin. Undan tashqari o’zgaruvchan reference dan o’zgarmas reference ham olib bo’lmaydi.
Sababi o’zgaruvchan reference lar ma’lumotni o’zgartirishi mumkin va agar biror o’zgaruvchi ma’lumotni o’qiyotganida, biror boshqa o’zgaruvchi qiymatni o’zgartirib qo’ysa, muammoga duch kelishimiz mumkin.
Tepada keltirib o’tilgan usullarga misol uchun PowerPointda prezentatsiya tayyorlash jarayonini olishimiz mumkin.
Birinchi vaziyat: O’zgaruvchan reference olish
Xodim Powerpoint da prezentatsiya qilayapti va u menejerdan yordam so’ramoqchi. Buning uchun, u menejerga login va parollarini topshiradi and menejerdan o’zgartirishlar kiritishni so’raydi. Endi menejerda xodimning prezentatsiyasiga o’zgartirish huquqi mavjud bo’ldi va u istalgan o’zgarishni qilishi mumkin. Bunday holatda hech qanday muammo yuzaga kelmaydi sababi o’zgaruvchan reference faqatgina menejerga berilgan.
Ikkinchi vaziyat: Faqatgina o’zgarmas reference
Xodim o’zi tayyorlagan prezentatsiyasini ish ofisidagi barcha bilan bo’lishadi va hammada prezentatsiyani o’qish imkoni mavjud bo’ladi, ya’ni o’zgarmas reference. Bunday holatda ham muammo yuzaga kelmaydi, sababi hech kim ma’lumotni o’zgartirish huquqiga ega emas.
Uchinchi vaziyat: Muammoli holat
Xodim prezentatsiyaning login parolini menejerga bergan lekin menejer hali prezentatsiyani oxirgi ko’rinishini xodimga bermasidan, xodim barcha hamkasblariga prezentatsiyain o’qish uchun tarqatadi. Lekin aynan shu vaqtda menejer unga o’zgartirish kiritishi ham mumkin. Bu esa anglashilmochiliklarga olib keladi albatta.
Quyidagi kodda o’zgaruvchan va o’zgarmas referencelarni keltirib o’tamiz:
fn main() {
let mut number = 10;
let number_ref = &number;
let number_change = &mut number;
*number_change += 10;
println!("{}", number_ref); // ⚠️
}
Kompilyator bizga muammoni tushunishimiz uchun foydali ma’lumot beradi:
error[E0502]: cannot borrow `number` as mutable because it is also borrowed as immutable
--> src\main.rs:4:25
|
3 | let number_ref = &number;
| ------- immutable borrow occurs here
4 | let number_change = &mut number;
| ^^^^^^^^^^^ mutable borrow occurs here
5 | *number_change += 10;
6 | println!("{}", number_ref);
| ---------- immutable borrow later used here
Lekin kod ishlaydi, Nega ?
fn main() {
let mut number = 10;
let number_change = &mut number; // o'zgaruvchan reference
*number_change += 10; // o'zgaruvchan referene orqali 10 qiymati qo'shamiz
let number_ref = &number; // o'zgarmas reference yaratamiz
println!("{}", number_ref); // o'zgarmas reference ni chop etamiz
}
Bu yerda kompilyator hech qanday muammolarsiz 20 ni chop etadi. Sababi, kompilyator tahlil qila oladiki biz “number_change” dan “number” ni o’zgartirish uchun foydalandik va uni boshqa ishlatmadik, shuning uchun ham hech qanday xatolik bermadi.
Oldinlari bunday holatlarda kompilyator xatolik berar edi, lekin endi kompilyator ancha aqilli bo’lgan va bunday holatlarni xatoliksiz hal qila oladi.
Soyalash:
Agar esingizda bo’lsa, soyalash(shadowing) usulidan foydalanganimizda biz o’zgaruvchini o’chirmasdan uni bloklab qo’yar edik. Ana endi biz uni ko’rish uchun reference dan foydalanishimiz mumkin.
fn main() {
let country = String::from("Austria");
let country_ref = &country;
let country = 8;
println!("{}, {}", country_ref, country);
}
Bizdagi natija “Austria,8” bo’ladi. sababi biz oldin “country” o’zgaruvchisida “String” ma’lumot turidagi qiymat e’lon qilamiz va undan “country_ref” nomli reference olamiz. Undan so’ng “country” ni soyalash usuli orqali qiymatini “8” ga o’zgartiramiz. Bilamizki, bizdagi birinci “String” qiymat o’chirib yuborilmagan, balki bloklanib qo’yilgan, shuning uchun ham “country_ref” da hali ham “Austria” qiymati mavjud
Leave a Reply