Ders 12 / 12
Modüller ve Kasalar
mod ve use birer öğedir: hiçbiri tek başına bir değer üretmez, biri bir ad sınırı çizer, öbürü var olan bir yolu kısaltır. Aynı ad hem modülün içinden hem dışından çağrılıyor ve pub yazılan/yazılmayan hâller karşılaştırılıyor; iki ayrı kaynak dosyası tek bir rustc çağrısıyla derlenip tek bir kasa oluşturuyor. Sınırlayıcı ölçüm görünürlüğün yolun her halkasında ayrı sağlanması gerektiğini gösteriyor: bir öğe pub olsa bile onu saran modül pub değilse dışarıdan erişilemez.
Yayın Güncelleme
Bu derste
- mod ve use bildirimlerinin birer öğe olduğunu ve tek başına değer üretmediğini gösterir
- Aynı adın modül içinden ve dışından çağrılmasını pub yazılan ve yazılmayan hâllerle karşılaştırır
- Bir modülün kasadan farkını iki kaynak dosyasının tek bir derleme biriminde birleşmesiyle ölçer
İçindekiler
Beş veri modelleme dersi kapandı ve hep aynı soruyu sordu: kaynakta yazılan bir şey bir değer
mi üretiyor? Bu soru hiçbir yerde, bir tipin ya da bir fonksiyonun kaynağın neresinde
göründüğüne değinmedi — bir yapı bildirimi, bir sözlük değişkeni, bir işlev, hangi sınırın
içinde tanımlı ve o sınırın dışından nasıl görülüyor? Kurulum ve Paket Yöneticisi dersi bu
soruyu bir kez ertelemişti: kaynak kökünün gerçek bir projede tek bir dosya olmadığını,
derleyicinin oradan başlayıp başka dosyalara mod bildirimleriyle ulaştığını söylemiş, ama
göstermemişti. Bu ders — kursun kapanışı — o ertelenen soruyu açıyor: mod ve use birer
değer mi üretiyor, yoksa yalnızca bir sınır mı çiziyor; ve bir modülün sınırı ile bir kasanın
sınırı aynı şey mi?
mod Bir Sınır Çizer, Kendisi Değer Üretmez
Rust’ın Tasarım Hedefleri dersinde mod olcu { pub fn birim() -> i32 { 3 } } biçiminde bir
modül zaten görülmüştü ve o dersin ölçüm çekirdeği mod bildirimini bir öğe saymıştı — ama
üstünde durmamıştı. Bu ders tam orada duruyor: mod ad { ... } satırı çalıştırıldığında
hiçbir şey üretmez. Yapılar dersindeki struct bildirimi gibi, derleyiciye bir ad ve bir
sınır tanıtır, kendisi değerlendirilmez. İçindeki her öğe — fonksiyon, sabit, başka bir modül
— ancak kullanıldığında bir değer doğurur.
// mod_ic_dis.rs — mod bir oge, ayni ad hem modul icinden hem disindan cagriliyor
mod olcum {
pub fn birim() -> i32 {
3
}
fn ozel_carpan() -> i32 {
10
}
pub fn buyutulmus() -> i32 {
birim() * ozel_carpan()
}
}
fn main() {
let disaridan = olcum::birim();
println!("{:<32}: {}", "olcum::birim() (pub, distan)", disaridan);
let ictekinden = olcum::buyutulmus();
println!("{:<32}: {}", "olcum::buyutulmus() (pub, distan)", ictekinden);
}
olcum::birim() (pub, distan) : 3 olcum::buyutulmus() (pub, distan): 30
RV20. olcum modülünün bildirimi hiçbir satırda çalışmadı; görülen iki çıktı da
birim ve buyutulmusün çağrıldığı satırlardan geldi. birim adı burada iki ayrı
konumdan çağrılıyor: main içinden olcum::birim() olarak — modülün dışından, tam yolla —
ve buyutulmusün gövdesinden birim() olarak — modülün içinden, hiçbir önek gerekmeden.
Aynı ad, aynı öğe, iki farklı konumdan aynı değeri (3) üretiyor; değişen yalnızca çağıranın
modül sınırının hangi tarafında durduğu.
ozel_carpan fonksiyonu pub taşımadan bildirildi ve yalnızca buyutulmusün gövdesinden,
yani olcum modülünün kendi içinden çağrılabildi. Bu, Rust’ta görünürlüğün varsayılan
olarak kapalı olduğunu gösteriyor: bir öğe, tanımlandığı modülün dışından, tek bir anahtar
sözcük — pub — eklenmeden görünmez. birim ile buyutulmus bu anahtar sözcüğü taşıdığı
için mainden erişilebildi; ozel_carpan taşımadığı için erişilemedi. Eğer main içine
olcum::ozel_carpan() yazılsaydı, bu satır derlenmezdi. Bu ret burada kod bloğuna
konmuyor — Desen Eşleme dersinde kurulan kuralla aynı gerekçeyle, derlenmeyen kaynak bloğa
girmiyor — ama nedeni tarif edilebilir: derleyici, çağrının pub taşımayan bir öğe üzerinden
modül sınırını geçmeye çalıştığını görür ve kaynağı reddeder.
Dosya Sınırı Modül Sınırına Dönüşür — Kasa Tek Derleme Birimidir
Kurulum ve Paket Yöneticisi dersi, kaynak kökünün bu kursta hep tek bir dosya olduğunu, ama
gerçek bir projede derleyicinin oradan başlayıp başka dosyalara mod bildirimleriyle
ulaştığını söylemişti. Burada gösteriliyor: mod ad; yazımı — gövdesiz, yalnızca noktalı
virgülle biten hâli — derleyiciye aynı dizindeki ad.rs dosyasını okumasını ve o dosyanın
tamamını ad adlı modülün gövdesi saymasını söylüyor.
// yardimci.rs — mod adi ile cekilen dosyanin tamami modulun govdesidir (KAYNAK)
pub fn disaridan_gorunur() -> i32 {
ozel_sabit() + 5
}
fn ozel_sabit() -> i32 {
100
}
// mod_dosya_siniri.rs — mod yardimci; bir dosya sinirini modul sinirina cevirir
mod yardimci;
fn main() {
let deger = yardimci::disaridan_gorunur();
println!("{:<34}: {}", "yardimci::disaridan_gorunur()", deger);
}
yardimci::disaridan_gorunur() : 105
RV21. Bu ölçümde iki ayrı kaynak dosyası var — mod_dosya_siniri.rs ve yardimci.rs —
ama derleme komutu bir kez çalıştı ve tek bir ikili üretti: iki dosya, bir kasa. Bu tek
derleme biriminin adı kasadır (crate): rustce verilen tek bir kaynak kökünden başlayıp
mod ile ulaşılan bütün dosyaların bir araya gelmesiyle oluşan, tek bir derleme adımından
geçen bütün. yardimci.rs içindeki ozel_sabit fonksiyonu pub taşımıyor; önceki bölümdeki
kuralın aynısı burada da geçerli — ozel_sabit, yalnızca yardimci modülünün kendi içinden,
yani disaridan_gorunurün gövdesinden çağrılabiliyor.
Modül ile kasa burada birbirine karışabilir, çünkü ikisi de bir sınır çiziyor, ama çizdikleri
sınırlar farklı düzlemde. Modül bir isim ve görünürlük sınırıdır; kaynağın tek bir dosyada mı
yoksa on dosyada mı durduğuyla ilgilenmez — önceki bölümdeki olcum bunu tek dosyanın içinde
gösterdi. Kasa ise bir derleme ve bağlama sınırıdır: kaç dosyadan, kaç modülden oluşursa
oluşsun, tek bir rustc çağrısından geçen her şey aynı kasanın parçasıdır. Bir kasa birden
çok modül taşıyabilir — mod_dosya_siniri.rs kaynak kökü ile yardimci modülü burada aynı
kasanın iki parçasıydı — ama bir modül asla birden çok kasaya bölünmez.
use Bir Öğedir: Kısayolun Kendisi Değer Üretmez
modun çizdiği sınır bir kez kurulduktan sonra, o sınırın içindeki bir adı her seferinde tam
yoluyla (olcum::birim()) yazmak zorunlu değildir. use bildirimi bir yolu kısaltan bir
addır ve tıpkı mod gibi bir öğedir: satırın kendisi hiçbir değer üretmez, yalnızca sonraki
satırların kullanabileceği kısa bir ad tanıtır.
// use_oge.rs — use bir oge, deger ancak kisayoldan gelen ad kullaninca dogar
mod olcum {
pub fn birim() -> i32 {
3
}
}
use olcum::birim;
fn main() {
let kisayoldan = birim();
let tam_yoldan = olcum::birim();
println!("{:<30}: {}", "birim() (use sonrasi kisayol)", kisayoldan);
println!("{:<30}: {}", "olcum::birim() (tam yol)", tam_yoldan);
println!("{:<30}: {}", "esit mi", kisayoldan == tam_yoldan);
}
birim() (use sonrasi kisayol) : 3 olcum::birim() (tam yol) : 3 esit mi : true
RV22. use olcum::birim; satırı mainden önce duruyor ve hiçbir çıktı doğrudan ona
bağlı değil — tıpkı bir önceki bölümdeki mod yardimci; gibi, kendisi çalıştırılmıyor.
İki çağrı da — kısayoldan birim() ve tam yoldan olcum::birim() — aynı değeri (3)
üretiyor; esit mi satırı bunu doğrudan doğruluyor. use bir kısayol tanıtıyor, yeni bir
hesaplama ya da yeni bir davranış değil: kısayoldan gelen değer ile tam yoldan gelen değer
arasında hiçbir fark yok, çünkü ikisi de aynı öğeye, olcum::birime, işaret ediyor. Bu, bir
önceki bölümdeki bulguyla aynı ailededir — bir bildirim kaynağa yeni bir hesaplama eklemez,
yalnızca sonraki satırların okuyabileceği bir ad ekler; mod bunu bir sınır için yapar,
use aynısını var olan bir sınırın içindeki bir yol için yapar.
Sınırlayıcı Ölçüm: Görünürlük Yolun Her Halkasında Ayrı Sağlanır
Buraya kadarki iki ölçüm görünürlüğü tek bir düzeyde gösterdi: bir öğe ya modülün dışına
pub taşıyordu ya taşımıyordu. Gerçek sınır bundan biraz daha ince: bir öğe pub olsa bile,
onu saran modül pub değilse, dışarıdan o öğeye ulaşılamaz.
// gorunurluk_zinciri.rs — gorunurluk yolun her halkasinda ayri ayri saglanmali
mod dis {
pub mod ic {
pub fn deger() -> i32 {
gizli() + 1
}
fn gizli() -> i32 {
6
}
}
}
fn main() {
let sonuc = dis::ic::deger();
println!("{:<30}: {}", "dis::ic::deger() (iki pub halka)", sonuc);
}
dis::ic::deger() (iki pub halka): 7
RV23. dis::ic::deger() çağrısı derlendi ve 7 verdi, çünkü yoldaki iki halka da —
ic modülü ve deger fonksiyonu — pub taşıyor; disin kendisi pub taşımıyor ama zaten
kaynak kökünün kendi düzeyinde tanımlı olduğu için dışarıdan (bu dosyanın kendisinden)
görünür durumda. Eğer ic modülü pub olmadan yalnızca mod ic { ... } yazılsaydı, deger
fonksiyonunun kendisi hâlâ pub kalsa bile dis::ic::deger() çağrısı derlenmezdi — çünkü
yol, pub taşımayan bir modül sınırından geçmek zorunda kalırdı. Bu kaynak da kod bloğuna
konmuyor, aynı derlenmeyen-kaynak kuralıyla; ama sonucu tarif edilebilir: derleyici için tek
bir öğenin görünürlüğü yetmiyor, yoldaki her adımın görünürlüğü ayrı ayrı sağlanmalı.
Bu, kursun kendi kapanışının sınırıdır da. Buradaki üç ölçüm — tek düzeyli pub/private
karşıtlığı, dosya sınırının modül sınırına dönüşmesi, çok halkalı görünürlük zinciri —
görünürlüğü ikili (açık ya da kapalı) bir anahtar gibi ele aldı. Rust’ın sunduğu ara
dereceler — yalnızca kasaya açık, yalnızca üst modüle açık gibi — bu derste hiç ölçülmedi,
çünkü ölçü ekseni hâlâ aynı soruydu: kaynakta yazılan bu şey bir değer mi üretiyor. Kaynakta
yazılan pub ile pub olmayan arasındaki fark tek bir ikili yanıt üretti; bu ikili yanıtın
kendi içindeki ince dereceler, bu eksenin dışında kalan ayrı bir konu.
Özet
modbildirimi bir öğedir: kendisi değer üretmez, yalnızca bir ad ve bir sınır tanıtır; aynı ad modülün içinden öneksiz, dışından tam yolla çağrılabilir.- Görünürlük varsayılan olarak kapalıdır; tek bir
pubanahtar sözcüğü bir öğeyi modülün dışına açar. mod ad;yazımı bir dosya sınırını modül sınırına çevirir; birden çok kaynak dosyası tek birrustcçağrısında derlenip tek bir kasa oluşturabilir.usebir öğedir: bir yolu kısaltan bir ad tanıtır, kendisi hiçbir değer üretmez; kısayoldan ve tam yoldan çağrılan aynı öğe aynı değeri verir.- Görünürlük yolun her halkasında ayrı sağlanmalıdır: bir öğe
pubolsa bile onu saran bir modülpubdeğilse dışarıdan erişilemez.
Kurs Kapanışı
Bu kurs, on iki ders boyunca tek bir soruyu sürdürdü: kaynakta yazılan bir şey bir değer mi üretiyor, yoksa yalnızca bir ad mı bildiriyor? İlk altı ders bu soruyu dilin en küçük birimlerine — ifadelere, bağlamalara, temel tiplere, denetim akışına — sordu; sonraki beş ders aynı soruyu veri modelleme araçlarına — yapılara, numaralandırmalara, desen eşlemeye, koleksiyonlara, sıralı ve karma yapılara — taşıdı. Bu son ders, sorunun kendisini değiştirmeden, kaynağın neresinde göründüğü sorusunu ekledi: bir öğe hangi sınırın içinde tanımlı ve o sınırın dışından nasıl görülüyor?
On iki dersin her biri kendi kesitini ölçtü ve kendi sınırlayıcı ölçümünü yazdı; aşağıdaki tablo bu on iki ölçümü tek bir yerde topluyor.
| Ders | Ölçülen yazım | Sınıfı (ifade · deyim · öğe) | Sınırlayıcı ölçüm |
|---|---|---|---|
| Rust’ın Tasarım Hedefleri | if/match bir dal seçip değer verir |
ifade | Sınıf işin doğasından değil, yöntemin imzasından okunur (insert ifade, push deyim) |
| Kurulum ve Paket Yöneticisi | giriş noktası, kaynak kökü, bildirim dosyası | öğe | Bildirim dosyası kaynağın içinde değil; kaynak değişmeden yalnız o dosya değişince çıktının adı değişir |
| Değişkenler ve Değişmezlik | let bağlaması |
deyim | Değişmezlik bağlamanın kendi sınırıdır; verinin başka yoldan paylaşılması ayrı bir soru (K02) |
| Temel Tipler | beş temel tipten değer kurmak | ifade | () değersiz değil, tek değerli bir tiptir |
| Fonksiyonlar ve İfade Odaklılığı | gövdenin son satırı (tail konumu) | ifade | Noktalı virgül değeri sessizce atar; hesaplama yine de gerçekleşir |
| Denetim Akışı | elsesiz if |
ifade | Değeri her zaman ()dir; gövdesi başka bir tip üretmeye kalkarsa derlenmez |
| Yapılar | struct bildirimi |
öğe | Demet yapısında sıra tek kimliktir; adlandırılmış yapıda alan sırası serbesttir |
| Numaralandırmalar | enum bildirimi |
öğe | Varyant sayısı durum sayısı değildir; veri taşıyan bir varyant sayılamayacak kadar durum taşır |
| Desen Eşleme | match ifadesi |
ifade | Bir yakalayıcı dal bütünlüğü sağlar ama korumaz: sonradan eklenen bir varyantı kendi mantığıyla ele almadan sessizce kapsar |
| Koleksiyonlar | push / insert |
deyim · ifade | insertin dönüş değeri bir değişkene bağlanmazsa, üzerine yazılan eski değer sessizce kaybolur |
| Sıralı ve Küme Yapıları | küme ekleme (insert → bool) |
ifade | Sıra güvencesi bir koşula bağlıdır: anahtar tipinin sıralanabilirlik koşulunu karşılaması gerekir |
| Modüller ve Kasalar | mod bildirimi / use |
öğe | Görünürlük yolun her halkasında ayrı sağlanır; bir öğe pub olsa bile onu saran modül değilse erişilemez |
Üç sınıf — ifade, deyim, öğe — kursun başından sonuna kadar değişmedi; değişen yalnızca bu
üç sınıfın uygulandığı yazımın genişliğiydi: tek bir satırdan bir fonksiyon gövdesine, bir
veri tipinin bildiriminden bir modülün sınırına. Sahiplik ve ödünç alma bu kursta defalarca
ertelendi — bir bağlamanın değişmezliği (Değişkenler ve Değişmezlik dersi), bir alıcının
&self işareti (Yapılar dersi), bir referansın çift & işareti (Koleksiyonlar dersi) her
seferinde bunun K02’nin konusu olduğu söylenerek geçildi. Sıradaki kurs bu ertelenen soruyu
açıyor: bir değerin sahibi kimdir, bir referans ödünç almak ne demektir ve bir değer
sahibinden ayrıldığında ne olur?
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.