use
kalit so'zi bilan yo'llarni doiraga kiritish
Funksiyalarni chaqirish yo'llarini yozishga to'g'ri kelishi noqulay va takroriy tuyulishi mumkin. 7-7-Ro'yxatda navbat_listiga_qoshish
funksiyasiga mutlaq yoki nisbiy yoʻlni tanladikmi, har safar navbat_listiga_qoshish
funksiyasiga murojat qilmoqchi boʻlganimizda, uyning_oldi
va xizmat
ni ham belgilashimiz kerak edi. Yaxshiyamki, bu jarayonni soddalashtirishning bir usuli bor: biz bir marta use
kalit so‘zi bilan yo‘lga nom yaratishimiz mumkin, so‘ngra boshqa hamma joyda qisqaroq nomdan foydalanishimiz mumkin.
7-11 ro'yxatda biz crate::uyning_oldi::xizmat
modulini restoranda_ovqatlanish
funksiyasi doirasiga kiritamiz, shuning uchun restoranda_ovqatlanish
dagi navbat_listiga_qoshish
funksiyasini chaqirish uchun faqat xizmat::navbat_listiga_qoshish
ni belgilashimiz kerak.
Fayl nomi: src/lib.rs
mod uyning_oldi {
pub mod xizmat {
pub fn navbat_listiga_qoshish() {}
}
}
use crate::uyning_oldi::xizmat;
pub fn restoranda_ovqatlanish() {
xizmat::navbat_listiga_qoshish();
}
use
va sohaga yo'lni qo'shish fayl tizimida ramziy havola yaratishga o'xshaydi. Crate ildiziga use crate::uyning_oldi::xizmat
ni qo‘shish orqali xizmat
endi bu doirada haqiqiy nom bo‘lib qoladi, xuddi xizmat
moduli crate ildizida aniqlangandek. use
doirasiga kiritilgan yo'llar boshqa yo'llar kabi maxfiylikni ham tekshiradi.
E'tibor bering, use
faqat use
ishlaydigan aniq doira uchun yorliqni yaratadi. 7-12 roʻyxat restoranda_ovqatlanish
funksiyasini mijoz
nomli yangi bolalar moduliga oʻtkazadi, bu keyinchalik use
statementidan farq qiladi, shuning uchun funksiyaning tanasi kompilyatsiya qilinmaydi:
Fayl nomi: src/lib.rs
mod uyning_oldi {
pub mod xizmat {
pub fn navbat_listiga_qoshish() {}
}
}
use crate::uyning_oldi::xizmat;
mod mijoz {
pub fn restoranda_ovqatlanish() {
xizmat::navbat_listiga_qoshish();
}
}
Kompilyator xatosi yorliq endi mijoz
modulida qo'llanilmasligini ko'rsatadi:
$ cargo build
Compiling restaurant v0.1.0 (file:///projects/restaurant)
warning: unused import: `crate::uyning_oldi::xizmat`
--> src/lib.rs:7:5
|
7 | use crate::uyning_oldi::xizmat;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
error[E0433]: failed to resolve: use of undeclared crate or module `xizmat`
--> src/lib.rs:11:9
|
11 | xizmat::navbat_listiga_qoshish();
| ^^^^^^ use of undeclared crate or module `xizmat`
For more information about this error, try `rustc --explain E0433`.
warning: `restaurant` (lib) generated 1 warning
error: could not compile `restaurant` due to previous error; 1 warning emitted
E'tibor bering, use
endi uning doirasida qo'llanilmasligi haqida ogohlantirish ham bor! Bu muammoni hal qilish uchun use
ni mijoz
moduliga ham o‘tkazing yoki mijoz
modulidagi super::xizmat
bilan ota-moduldagi yorliqlarga murojaat qiling.
use
bilan idiomatik yo'llarni yaratish
7-11 ro'yxatda siz shunday deb hayron bo'lishingiz mumkin,Nima uchun biz bir xil natijaga erishish uchun navbat_listiga_qoshish
funksiyasigacha toʻliq yoʻlni ishlatish oʻrniga, crate::uyning_oldi::xizmat
ni ishlatishni belgilab qoʻydik va keyin restoranda_ovqatlanish
ichidagi xizmat::navbat_listiga_qoshish
ga murojat qildik, 7-13 ro'yxatdagi kabi.
Fayl nomi: src/lib.rs
mod uyning_oldi {
pub mod xizmat {
pub fn navbat_listiga_qoshish() {}
}
}
use crate::uyning_oldi::xizmat::navbat_listiga_qoshish;
pub fn restoranda_ovqatlanish() {
navbat_listiga_qoshish();
}
Garchi 7-11 va 7-13 ro'yxatlari bir xil vazifani bajarsa-da, 7-11 ro'yxat funksiyani use
bilan qamrab olishning idiomatik usulidir. Funksiyaning ota-modulini use
bilan qamrab olish funksiyani chaqirishda ota-modulni belgilashimiz kerakligini anglatadi. Funksiyani chaqirishda ota-modulni ko'rsatish, to'liq yo'lning takrorlanishini minimallashtirish bilan birga, funksiya mahalliy sifatida aniqlanmaganligini aniq ko'rsatadi. 7-13 ro'yxatda navbat_listiga_qoshish
qayerda aniqlangani aniq emas.
Boshqa tomondan, use
bilan structlar, enumlar va boshqa elementlarni keltirishda to'liq yo'lni ko'rsatish idiomatikdir. 7-14 ro'yxat standart kutubxonaning HashMap
structini binary crate doirasiga olib kirishning idiomatik usulini ko'rsatadi.
Fayl nomi: src/main.rs
use std::collections::HashMap; fn main() { let mut map = HashMap::new(); map.insert(1, 2); }
Bu idioma ortida hech qanday yaxshi sabab yo'q: Bu shunchaki konventsiya paydo bo'ldi va odamlar Rust kodini shu tarzda o'qish va yozishga o'rganib qolgan.
Bu idiomadan istisno shundaki, biz bir xil nomdagi ikkita elementni use
statementi yordamida doiraga kiritganimizda - Rust bunga yo'l qo'ymaydi. 7-15 ro'yxatda bir xil nomga ega, ammo har xil ota-modullarga ega bo'lgan ikkita Result
turini qanday ko'rinishga kiritish va ularga qanday murojaat qilish kerakligi ko'rsatilgan.
Fayl nomi: src/lib.rs
use std::fmt;
use std::io;
fn funksiya1() -> fmt::Result {
// --snip--
Ok(())
}
fn funksiya2() -> io::Result<()> {
// --snip--
Ok(())
}
Ko'rib turganingizdek, ota-modullardan foydalanish ikkita Result
turini ajratib turadi.
Buning o'rniga use std::fmt::Result
va us std::io::Result
ni belgilagan bo'lsak, bizda bir xil miqyosda ikkita Result
turi bo'lar edi va Rust Result
dan foydalanganda qaysi birini nazarda tutganimizni bilmas edi.
as
kalit so'zi bilan yangi nomlarni taqdim etish
Bir xil nomdagi ikkita turni use
bilan bir xil doiraga olib kirish muammosining yana bir yechimi bor: yoʻldan soʻng biz as
va yangi mahalliy nom yoki tur uchun taxallus belgilashimiz mumkin. 7-16 ro'yxatda ikkita Result
turidan birini as
yordamida qayta nomlash orqali 7-15 ro'yxatdagi kodni yozishning yana bir usuli ko'rsatilgan.
Fayl nomi: src/lib.rs
use std::fmt::Result;
use std::io::Result as IoResult;
fn funksiya1() -> Result {
// --snip--
Ok(())
}
fn funksiya2() -> IoResult<()> {
// --snip--
Ok(())
}
Ikkinchi use
statementida biz std::io::Result
turi uchun yangi IoResult
nomini tanladik, bu endi std::fmt
dan Result
turiga zid kelmaydi, u ham doiraga kiradi. 7-15 va 7-16 ro'yxatlar idiomatik hisoblanadi, shuning uchun tanlov sizga bog'liq!
pub use
bilan nomlarni qayta eksport(re-eksport) qilish
use
kalit so'zidan foydalanib, nomni qamrovga kiritganimizda, yangi doirada mavjud bo'lgan nom private bo'ladi. Bizning kodimizni chaqiradigan kodni xuddi shu kod doirasida aniqlangandek ushbu nomga murojaat qilishini yoqish uchun biz pub
va use
ni birlashtira olamiz. Bu usul re-eksport deb nomlanadi, chunki biz obyektni qamrovga kiritmoqdamiz, lekin elementni boshqa qamrovlarga kiritish uchun ham mavjud qilamiz.
7-17 ro'yxatda 7-11 ro'yxatdagi kod ko'rsatilgan, ildiz modulidagi use
pub use
ga o'zgartirilgan.
Fayl nomi: src/lib.rs
mod uyning_oldi {
pub mod xizmat {
pub fn navbat_listiga_qoshish() {}
}
}
pub use crate::uyning_oldi::xizmat;
pub fn restoranda_ovqatlanish() {
xizmat::navbat_listiga_qoshish();
}
Ushbu o'zgarishdan oldin tashqi kod restoran::uyning_oldi::xizmat::navbat_listiga_qoshish()
yo'lidan foydalanib, navbat_listiga_qoshish
funksiyasini chaqirishi kerak bo'ladi. Endi bu pub use
xizmat
modulini ildiz modulidan qayta eksport qilgan bo‘lsa, tashqi kod endi restoran::xizmat::navbat_listiga_qoshish()
yo‘lidan foydalanishi mumkin..
Qayta eksport qilish sizning kodingizning ichki tuzilishi sizning kodingizni chaqirayotgan dasturchilarning domen haqida o'ylashlaridan farq qilganda foydali bo'ladi. Misol uchun, ushbu restoran metaforasida restoranni boshqaradigan odamlar "uyning old tomoni" va "uyning orqasi" haqida o'ylashadi. Ammo restoranga tashrif buyurgan mijozlar, ehtimol, restoranning qismlari haqida o'ylamaydilar. pub use
bilan biz kodimizni bitta struct bilan yozishimiz mumkin, lekin boshqa structni ko'rsatamiz. Bu bizning kutubxonamizni kutubxonada ishlaydigan dasturchilar va kutubxonaga murojat qilayotgan dasturchilar uchun uchun yaxshi tashkil etilgan holda saqlaydi. Biz 14-bobning “pub use
bilan qulay umumiy APIni eksport qilish” bo‘limida pub use
ning yana bir misolini va uning cratengiz hujjatlariga qanday ta’sir qilishini ko‘rib chiqamiz.
Tashqi paketlardan foydalanish
2-bobda biz tasodifiy raqamlarni olish uchun rand
deb nomlangan tashqi paketdan foydalangan holda taxminiy o'yin loyihasini dasturlashtirdik. Loyihamizda rand
dan foydalanish uchun biz ushbu qatorni Cargo.toml ga qo'shdik:
Fayl nomi: Cargo.toml
rand = "0.8.5"
Cargo.toml-ga rand
ni dependency sifatida qo'shish Cargo-ga crates.io-dan rand
paketini va har qanday bog'liqliklarni yuklab olishni va rand
ni loyihamiz uchun ishlatishni aytadi.
Keyin, rand
ta'riflarini paketimiz doirasiga kiritish uchun biz crate nomidan boshlanadigan use
qatorini qo'shdik, rand
va biz qamrab olmoqchi bo'lgan elementlarni sanab o'tdik. Eslatib o‘tamiz, 2-bobdagi “Tasodifiy raqamni yaratish” bo‘limida biz Rng
traitini qamrab oldik va rand::thread_rng
funksiyasini chaqirdik:
use std::io;
use rand::Rng;
fn main() {
println!("Raqamni topish o'yini!");
let yashirin_raqam = rand::thread_rng().gen_range(1..=100);
println!("Yashirin raqam: {yashirin_raqam}");
println!("Iltimos, taxminingizni kiriting.");
let mut taxmin = String::new();
io::stdin()
.read_line(&mut taxmin)
.expect("Satrni o‘qib bo‘lmadi");
println!("Sizning taxminingiz: {taxmin}");
}
Rust hamjamiyatining a'zolari crates.io saytida ko'plab paketlarni taqdim etishdi va ulardan birini o'z paketingizga olish xuddi shu bosqichlarni o'z ichiga oladi: ularni paketingizning Cargo.toml faylida roʻyxatga kiriting va use
dan foydalanib, ularni cratelaridagi elementlarni qamrab oling.
E'tibor bering, standart std
kutubxonasi bizning paketimizdan tashqarida joylashgan cratedir. Standart kutubxona Rust tili bilan birga kelganligi sababli, biz Cargo.toml ni std
qo'shish uchun o'zgartirishimiz shart emas. Ammo biz u yerdan elementlarni paketimiz doirasiga olib kirish uchun use
bilan murojaat qilishimiz kerak. Masalan, HashMap
bilan biz ushbu qatordan foydalanamiz:
#![allow(unused)] fn main() { use std::collections::HashMap; }
Bu standart kutubxona cratesining nomi bo'lgan std
bilan boshlanadigan mutlaq yo'ldir.
Uzun use
ro'yxatini qisqartirish uchun ichki yo'llardan foydalanish
Agar biz bir xil crate yoki bir xil modulda belgilangan bir nechta elementlardan foydalansak, har bir elementni o'z qatoriga qo'yish bizning fayllarimizda juda ko'p vertikal joy egallashi mumkin. Masalan, 2-4 roʻyxatdagi raqamlarni taxmin qilish dasturida mavjud boʻlgan ushbu ikkita use
statementi std
dagi elementlarni qamrab oladi:
Filename: src/main.rs
use rand::Rng;
// --snip--
use std::cmp::Ordering;
use std::io;
// --snip--
fn main() {
println!("Raqamni topish o'yini!");
let yashirin_raqam = rand::thread_rng().gen_range(1..=100);
println!("Yashirin raqam: {yashirin_raqam}");
println!("Iltimos, taxminingizni kiriting.");
let mut taxmin = String::new();
io::stdin()
.read_line(&mut taxmin)
.expect("Satrni o'qib bo'lmadi");
println!("Sizning taxminingiz: {taxmin}");
match taxmin.cmp(&yashirin_raqam) {
Ordering::Less => println!("Raqam Kichik!"),
Ordering::Greater => println!("Raqam katta!"),
Ordering::Equal => println!("Siz yutdingiz!"),
}
}
Buning o'rniga, biz bir xil elementlarni bir qatorga kiritish uchun ichki yo'llardan foydalanishimiz mumkin. Buni 7-18 roʻyxatda koʻrsatilganidek, yoʻlning umumiy qismini, keyin ikkita nuqta qoʻyib, soʻngra yoʻllarning bir-biridan farq qiladigan qismlari roʻyxati atrofida jingalak qavslarni belgilash orqali qilamiz.
Fayl nomi: src/main.rs
use rand::Rng;
// --snip--
use std::{cmp::Ordering, io};
// --snip--
fn main() {
println!("Raqamni topish o'yini!");
let yashirin_raqam = rand::thread_rng().gen_range(1..=100);
println!("Yashirin raqam: {yashirin_raqam}");
println!("Iltimos, taxminingizni kiriting.");
let mut taxmin = String::new();
io::stdin()
.read_line(&mut taxmin)
.expect("Satrni o'qib bo'lmadi");
let taxmin: u32 = taxmin.trim().parse().expect("Iltimos, raqam yozing!");
println!("Sizning taxminingiz: {taxmin}");
match taxmin.cmp(&yashirin_raqam) {
Ordering::Less => println!("Raqam Kichik!"),
Ordering::Greater => println!("Raqam katta!"),
Ordering::Equal => println!("Siz yutdingiz!"),
}
}
Kattaroq dasturlarda bir xil crate yoki moduldan ko'plab elementlarni o'rnatilgan yo'llar yordamida qamrab olish juda ko'p talab qilinadigan alohida use
statementlari sonini kamaytirishi mumkin!
Siz har qanday darajadagi ichki yo'ldan foydalanishingiz mumkin, bu yo'l qismini ulashuvchi ikkita use
statementini birlashtirishda foydalidir. Masalan, 7-19 ro'yxat ikkita use
statementini ko'rsatadi: biri std::io
ni qamrab oladi va ikkinchisi std::io::Write
ni qamrab oladi.
Fayl nomi: src/lib.rs
use std::io;
use std::io::Write;
Ushbu ikkita yo'lning umumiy qismi std::io
va to'liq birinchi yo'ldir. Ushbu ikkita yo'lni bitta use
statementiga birlashtirish uchun biz 7-20 ro'yxatda ko'rsatilganidek, ichki yo'lda self
dan foydalanishimiz mumkin.
Fayl nomi: src/lib.rs
use std::io::{self, Write};
Bu satr std::io
va std::io::Write
ni qamrab oladi.
Glob operatori
Agar biz yo'lda belgilangan barcha umumiy elementlarni qamrovga kiritmoqchi bo'lsak, biz *
glob operatori tomonidan keyingi yo'lni belgilashimiz mumkin:
#![allow(unused)] fn main() { use std::collections::*; }
Ushbu use
statementi std::collections
da aniqlangan barcha public elementlarni joriy doiraga olib keladi. Glob operatoridan foydalanganda ehtiyot bo'ling! Glob qaysi nomlar qamrovda ekanligini va dasturingizda ishlatiladigan nom qayerda aniqlanganligini aniqlashni qiyinlashtirishi mumkin.
Glob operatori ko'pincha sinovdan o'tgan hamma narsani tests
moduliga kiritish uchun test paytida ishlatiladi; biz bu haqda 11-bobdagi "Testlarni qanday yozish kerak" bo'limida gaplashamiz. Glob operatori ba'zan prelude patterning bir qismi sifatida ham qo'llaniladi: ushbu pattern haqida qo'shimcha ma'lumot olish uchun standart kutubxona texnik hujjatlariga qarang.