---
title: 'Sahiplik ve Bellek Modeli'
source: 'https://academia.sh/tr/kurslar/sahiplik'
language: tr
updated: '2026-09-13T05:09:24+00:00'
license: 'CC BY-SA 4.0'
lessons: 14
outcomes:
    - 'Sahiplik, ödünç alma ve yaşam süresi kurallarını gerekçeleriyle açıklar'
    - 'Bir değerin ömrünün nerede bittiğini koşturarak ölçer'
    - 'Ödünç denetleyicisinin reddettiği yazımı tasarım değişikliğiyle çözer'
    - 'Paylaşımlı sahiplik ve iç değişebilirlik araçlarını koşullarıyla kullanır'
---

# Sahiplik ve Bellek Modeli

Rust'ta bir değerin belleği kimsenin sonradan karar vermediği bir noktada geri veriliyor ve o nokta kaynaktan okunabiliyor: kurs her düzeneği tek bir soruyla ölçer — bu değerin ömrü nerede bitiyor? Taşıma, ödünç alma, dilimler, yaşam süresi açıklamaları, öbekte tekil sahiplik, referans sayımı ve iç değişebilirlik aynı çerçeveden geçirilir.

## Sahiplik Kuralları

Değerin nerede yaşadığının tipte görünür olması, tek sahip kuralının taşımayı zorunlu kılması, ödünç almanın sahipliği devretmeden erişim vermesi, dilimin sahiplik almadan veri görüntülemesi, ve bütün bunları derleme zamanında sınayan denetleyicinin neyi güvence altına aldığı.

### Yığıt ve Öbek

Source: https://academia.sh/tr/kurslar/sahiplik/yigit-ve-obek

On dört değerlik bir ölçüm çekirdeği koşturulur ve her değerin ömrünü dört sınıftan birine yerleştirir — kapsam sonu, taşındığı yerde, açık çağrıda, kabıyla birlikte; sonuç 6/3/1/4 olarak sabittir. Kapsam sonunda biten değerlerin bitiş sırasının bildirim sırasının tam tersi olduğu ve öbeğe alınan bir değerin de aynı deftere düştüğü ölçülür.

Önceki kurs kaynakta yazılan bir satırın ne ürettiğini ölçtü: ifade, deyim, öğe. Bu üçlü
sınıflandırma bir satırın çalıştırıldığı anda ne olduğunu belirliyordu, ama bilerek sormadığı
bir soru kaldı — o satırın ürettiği değer ne kadar yaşıyor. Bu kurs tam oraya bakıyor ve
bütün dersleri boyunca tek bir soru soruluyor: bu değerin ömrü nerede bitiyor?

Bu soru daha önce farklı bir bağlamda karşımıza çıkmıştı. Eşzamanlılık kursu (M09/K03) bir
goroutine'in nasıl duracağını ölçtü — koşan bir birimin sonlanması. Bu kurs aynı fiili farklı
bir özneye uyguluyor: orada koşan bir birim duruyordu, burada bir değer bitiyor. Bir birimin
durması dışarıdan bir kararla (kanal kapanması, bağlam iptali) tetiklenirken, bir değerin
bitişi kaynağın kendi yapısından okunabiliyor — ayrı bir karar mekanizmasına ihtiyaç
duymadan.

#### Dört Yanıt

Rust'ta bir değerin ömrü dört biçimden birinde bitiyor ve kurs boyunca bu dört ad
değişmiyor.

| Sınıf | Tanım |
|---|---|
| kapsam sonu | Değer, bağlandığı bloğun sonunda biter |
| taşındığı yerde | Sahiplik başkasına geçti; ömür yeni sahibin bittiği yerde biter |
| açık çağrıda | Kaynakta yazılı bir çağrı ömrü erken bitirir |
| kabıyla birlikte | Değer bir kabın içindedir; kap bitince o da biter |

Bu dört sınıf birbirini dışlıyor: bir değer aynı anda hem kapsam sonunda hem taşındığı
yerde bitemez, çünkü taşınan bir değerin eski bağlaması zaten canlı değil — bitiş, bir
değerin hayatında yalnız bir kez, dört yoldan tam biriyle gerçekleşiyor. Bitiş noktası
kaynağın kendi yapısından okunuyor ve bir çalışma zamanı kararına bağlı değil; bu yüzden
ölçüm bir süre ya da bir sayaç değil, sıralı bir kayıt üretiyor — hangi değerin ne zaman
bittiğinin listesi.

Programlama Temelleri kursu (M01/K02) kapsam (scope) kavramını zaten kurmuştu: bir adın
hangi blokta göründüğü ve o bloktan çıkınca adın erişilemez hâle geldiği. Bu kurs aynı
kavramı tekrar tanımlamıyor; pay, Rust'ın kapsamı yalnız bir görünürlük sınırı olarak değil,
bir **bitiş noktası** olarak da kullanmasında. Bir adın kapsam dışına çıkması, çoğu dilde
yalnız o ada bir daha erişilemeyeceği anlamına gelir; burada aynı olay, adın tuttuğu değerin
de sonlandığı anlamına geliyor — ve bu sonlanma, derleme zamanında bilinen bir noktada,
çalışma zamanında kesin olarak gerçekleşiyor.

#### Ölçüm Çekirdeği

Kursun geri kalanında kullanılan çekirdek `omur.rs`'dir. On dört ayrı değer dört bölüm
halinde (A, B, C, D) oluşturuluyor, her değerin bitişi ortak bir gözlem defterine
yazılıyor ve sonunda sınıf başına toplam basılıyor.

Her bölüm kendi ölçümünü aynı yöntemle alıyor: bölüm başlamadan önce defterin o anki
uzunluğu (`a0`, `b0`, `c0`, `d0`) kaydediliyor, bölümün kapsamı kapandıktan sonra
`yeni_olanlar` işlevi yalnız o uzunluktan sonra eklenen satırları döndürüyor. Bu, dört
bölümün birbirinin ölçümüne karışmasını engelliyor — A bölümünde biten üç değer, B
bölümünün ölçümünde bir daha görünmüyor, çünkü B'nin başlangıç noktası zaten A bittikten
sonraki uzunluğu alıyor. Aynı defter dördü için de ortak, ama her bölüm kendi payını
kendi başlangıç noktasından itibaren okuyor.

Gözlem defteri `Defter` tipiyle tutuluyor — birden çok `Iz` örneğinin aynı listeye
yazabilmesini sağlayan paylaşılan bir kayıt. Bu paylaşımın kendi iç yapısı
(`Rc<RefCell<Vec<String>>>`) ölçüm aracının bir tasarım kararıdır; nasıl çalıştığı Referans
Sayımı ve İç Değişebilirlik derslerinde ayrı birer konu olarak ele alınacak. Burada önemli
olan yalnız şu: her `Iz` değeri `Drop` trait'ini uyguluyor, yani bir değerin ömrü bittiğinde
derleyici otomatik olarak bir kapanış kodu çalıştırıyor ve bu kod kendi adını deftere
ekliyor. `Drop`'un kendi kuralları (hangi tiplerin onu uygulayabildiği, `Clone`/`Copy` ile
ilişkisi) bu kursun konusu değil; ölçülen tek şey bu tetiklenmenin kaynakta **nerede**
gerçekleştiği.

**SK1.** `Defter` ve `Iz`'in kendisi ölçüm aracının tasarım kararıdır, dilin bir zorunluluğu
değil; bir değerin hangi sınıfa girdiğine karar veren şey kodun kendi yapısıdır — bir
kapsamın kapanması, bir taşıma, açık bir çağrı ya da bir kabın içinde olmak. `Iz` tipi bu
dört durumu görünür kılmak için yazıldı, kendisi bunlardan biri değil.

```rust
// omur.rs — bir degerin omru nerede bitiyor: kapsam sonunda mi, tasindigi yerde mi,
// acik cagrida mi, yoksa kabiyla birlikte mi.

use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz {
            ad: ad.to_string(),
            defter: Rc::clone(defter),
        }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

struct Kutu {
    icerik: Iz,
}

fn yut(_alinan: Iz) {
    // Deger buraya tasindi; govde bitince omru burada bitiyor.
}

fn okunan(defter: &Defter) -> Vec<String> {
    defter.borrow().clone()
}

fn yeni_olanlar(defter: &Defter, onceki: usize) -> String {
    let hepsi = okunan(defter);
    hepsi[onceki..].join(", ")
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    let mut sayim: Vec<(&str, &str)> = Vec::new();

    // --- A: kapsam sonu ---
    let a0 = okunan(&defter).len();
    {
        let _birinci = Iz::yeni("kapsam-1", &defter);
        let _ikinci = Iz::yeni("kapsam-2", &defter);
        let _ucuncu = Iz::yeni("kapsam-3", &defter);
    }
    println!("A kapsam sonu       -> {}", yeni_olanlar(&defter, a0));
    for ad in ["kapsam-1", "kapsam-2", "kapsam-3"] {
        sayim.push((ad, "kapsam sonu"));
    }

    // Golgelenen deger de kapsam sonuna kadar yasar: yeni baglama eskisini bitirmiyor.
    let g0 = okunan(&defter).len();
    {
        let _golge = Iz::yeni("golgelenen", &defter);
        let _golge = Iz::yeni("golgeleyen", &defter);
        println!("   golgeleme aninda -> {}", yeni_olanlar(&defter, g0));
    }
    println!("A golgeleme         -> {}", yeni_olanlar(&defter, g0));
    sayim.push(("golgelenen", "kapsam sonu"));
    sayim.push(("golgeleyen", "kapsam sonu"));

    // --- B: tasindigi yerde ---
    let b0 = okunan(&defter).len();
    {
        let tasinan = Iz::yeni("islev-icine", &defter);
        yut(tasinan);
        println!("   islev doner donmez -> {}", yeni_olanlar(&defter, b0));

        let ic = Iz::yeni("ic-kapsama", &defter);
        {
            let _yeni_sahip = ic;
        }
        println!("   ic kapsam biter bitmez -> {}", yeni_olanlar(&defter, b0));

        let alan = Iz::yeni("yapi-icine", &defter);
        {
            let kutu = Kutu { icerik: alan };
            let _ad_uzunlugu = kutu.icerik.ad.len();
        }
    }
    println!("B tasindigi yerde   -> {}", yeni_olanlar(&defter, b0));
    for ad in ["islev-icine", "ic-kapsama", "yapi-icine"] {
        sayim.push((ad, "tasindigi yerde"));
    }

    // --- C: acik cagrida ---
    let c0 = okunan(&defter).len();
    {
        let erken = Iz::yeni("erken-birakilan", &defter);
        let _gec = Iz::yeni("kapsamda-kalan", &defter);
        drop(erken);
        println!("   acik cagridan sonra -> {}", yeni_olanlar(&defter, c0));
    }
    println!("C acik cagrida      -> {}", yeni_olanlar(&defter, c0));
    sayim.push(("erken-birakilan", "acik cagrida"));
    sayim.push(("kapsamda-kalan", "kapsam sonu"));

    // --- D: kabiyla birlikte ---
    let d0 = okunan(&defter).len();
    {
        let mut liste = Vec::new();
        liste.push(Iz::yeni("kap-1", &defter));
        liste.push(Iz::yeni("kap-2", &defter));
        liste.push(Iz::yeni("kap-3", &defter));
        let _obekte = Box::new(Iz::yeni("obekte", &defter));
        println!("   kap dolu iken -> [{}]", yeni_olanlar(&defter, d0));
    }
    println!("D kabiyla birlikte  -> {}", yeni_olanlar(&defter, d0));
    for ad in ["kap-1", "kap-2", "kap-3", "obekte"] {
        sayim.push((ad, "kabiyla birlikte"));
    }

    // --- rapor ---
    let biten = okunan(&defter);
    println!();
    println!("toplam biten deger: {}", biten.len());

    let siniflar = ["kapsam sonu", "tasindigi yerde", "acik cagrida", "kabiyla birlikte"];
    for sinif in siniflar {
        let adet = sayim.iter().filter(|(_, s)| *s == sinif).count();
        println!("{:<18}{}", sinif, adet);
    }
}
```

```
A kapsam sonu       -> kapsam-3, kapsam-2, kapsam-1
   golgeleme aninda -> 
A golgeleme         -> golgeleyen, golgelenen
   islev doner donmez -> islev-icine
   ic kapsam biter bitmez -> islev-icine, ic-kapsama
B tasindigi yerde   -> islev-icine, ic-kapsama, yapi-icine
   acik cagridan sonra -> erken-birakilan
C acik cagrida      -> erken-birakilan, kapsamda-kalan
   kap dolu iken -> []
D kabiyla birlikte  -> obekte, kap-1, kap-2, kap-3

toplam biten deger: 14
kapsam sonu       6
tasindigi yerde   3
acik cagrida      1
kabiyla birlikte  4
```

#### Dört Bölümün Okunuşu

A bölümü üç değer kuruyor (`kapsam-1`, `kapsam-2`, `kapsam-3`) ve iç kapsam kapanır kapanmaz
üçü de deftere düşüyor — çıktıda `kapsam-3, kapsam-2, kapsam-1` sırasıyla. Bu sıralamaya
Sınırlayıcı Ölçüm bölümünde dönülecek. A bölümünün ikinci kısmı gölgelemeyi ölçüyor: aynı
ada iki kez bağlanmak (`golgelenen`, sonra `golgeleyen`) tek bir bitiş üretmiyor, ikisi ayrı
ayrı yaşıyor ve ikisi de kapsam sonunda bitiyor. Gölgeleme anında alınan ölçüm boş çıkıyor
çünkü henüz hiçbir şey bitmedi; gölgeleme yalnız yeni bir bağlama kuruyor, eskisinin ömrünü
kısaltmıyor. Programlama Temelleri kursu (M01/K02) gölgelemeyi kavram olarak kurmuştu ve
Değişkenler ve Değişmezlik dersi (M10/K01) onu tip değiştirebilme yönüyle derinleştirmişti;
buradaki pay dar: gölgeleme bir bitiş değildir.

B bölümü aynı sınıfa düşen üç ayrı taşıma biçimini gösteriyor: bir değerin işleve
geçirilmesi (`islev-icine`), bir iç kapsama yeniden bağlanması (`ic-kapsama`) ve bir yapının
alanına konması (`yapi-icine`). Üçü de dış kapsam kapanmadan önce bitiyor, çünkü sahiplik
her seferinde daha dar bir kapsama taşınıyor ve o dar kapsam önce kapanıyor. `yut` işlevi
ve `Kutu` yapısı bu üç biçimi somutlaştırmak için çekirdeğe eklendi: `yut` bir değeri
parametre olarak alıp hiçbir şey döndürmeden kapsamının sonunda bırakıyor, `Kutu` ise bir
değeri kendi alanına yerleştirip o alanın sahibinin artık `Kutu` örneği olduğunu gösteriyor.
İkisi de dilin bir parçası değil, üç taşıma biçimini yan yana koymak için yazılmış küçük
yardımcılar. Bu üç biçimin ayrıntısına Sahiplik ve Taşıma dersinde girilecek; burada yalnız
üçünün de aynı sınıfa (taşındığı yerde) girdiği görülüyor.

C bölümü tek bir örnekle nadir bir sınıfı gösteriyor: aynı kapsamdaki iki değerden biri
(`erken-birakilan`) bir çağrıyla kapsamı bitmeden bırakılıyor, öbürü (`kapsamda-kalan`)
normal kapsam sonuna kadar bekliyor. On dört değerden yalnız biri bu yolla bitiyor — açık
çağrı, kapsamın kendi akışını beklemeden bir bitişi öne çekiyor.

D bölümü dört değeri tek bir kapta topluyor: bir büyüyen dizi üç eleman tutuyor (`kap-1`,
`kap-2`, `kap-3`) ve öbeğe alınmış tekil bir değer (`obekte`) aynı kapsamda duruyor. Kap
dolu iken defter boş çıkıyor — kap kapanmadan hiçbir eleman bitmiyor. Kap kapandığında dört
değer de aynı anda deftere düşüyor, ama kendi aralarındaki sırayı koruyorlar: `obekte`
listeden önce bitiyor (bildirimin tersi), listenin kendi elemanları ise eklendikleri
sırayla bitiyor.

**SK2.** Büyüyen dizi içindeki elemanların bırakılma sırası (ekleme sırasıyla, indeks
küçükten büyüğe) dilin kendi güvencesidir; bu davranış çekirdeğin seçtiği bir örnek değil,
standart kütüphanenin tanımladığı bir kuraldır.

#### Yığıt, Öbek ve Tek Sahip

Bellek düzeninin kendisi bu kursun konusu değil — Bilgisayarlar Nasıl Çalışır kursu
(M01/K01) ve Kaçış Çözümlemesi dersi (M09/K05) yığıt ve öbek ayrımını kavram olarak zaten
kurmuştu, bu üçüncü karşılaşma bir kuram tekrarı değil. Buradaki pay dar ve iki cümleyle
özetlenebilir: ayrım **tipte görünür** ve her değerin **tek bir sahibi** var.

`obekte` değişkeni bunu somutlaştırıyor. Sıradan bir `Iz` değeri (örneğin `kapsam-1`)
doğrudan kendi bağlandığı yerde duruyor; `Box::new(Iz::yeni("obekte", &defter))` ise değeri
öbeğe yerleştiriyor ve bu yerleştirme kodda görünüyor — tipin kendisi `Box<Iz>`, `Iz`
değil. Öbeğe alma konusunun kendisi (özyinelemeli tiplerin nasıl mümkün kıldığı, sahipliğin
nasıl davrandığı) ileride Öbekte Tekil Sahiplik dersinde ele alınacak. Burada görülmesi
gereken tek şey şu: `obekte` de tıpkı yığıttaki üç dizi elemanı gibi aynı deftere, aynı
`Drop` mekanizmasıyla düşüyor. Bir değerin nerede yaşadığı (yığıtta mı öbekte mi) ile ne
zaman bittiği ayrı sorular — biri tipten okunuyor, öbürü kapsamdan.

"Tek sahip" ifadesi burada bir slogan değil, defterin kendisinden okunan bir gözlem.
On dört değerin hiçbiri deftere iki kez düşmüyor — her ad, çıktının tamamında tam olarak bir
kez görünüyor. Bir değerin yığıtta mı öbekte mi durduğu değişse bile bu tekillik değişmiyor:
`obekte` de, `kap-1` de, `kapsam-1` de birer kez bitiyor. Bu gözlem rastgele değil; bir
değerin aynı anda iki ayrı yerde sahiplenilmesi mümkün olsaydı, o değer iki kez bitirilmeye
çalışılır ve defterde aynı ad iki kez görünürdü. Sıradaki ders bu tekilliğin taşıma
sırasında nasıl korunduğunu — sahiplik el değiştirirken eski sahibin neden artık o değere
erişemediğini — doğrudan ölçüyor.

#### Sınırlayıcı Ölçüm: Bitiş Sırası Bildirimin Tersidir

A bölümünün üç değeri bunu en açık gösteren örnek. `kapsam-1`, `kapsam-2`, `kapsam-3`
sırasıyla bildiriliyor, ama iç kapsam kapandığında bitiş sırası tam ters:
`kapsam-3, kapsam-2, kapsam-1`. Bu bir ölçüm aracının kendi seçimi değil, dilin kendi
sözü.

**SK3.** Yerel bir kapsamdaki değerler her zaman bildirimin tersi sırayla bitiyor — bu
Rust'ın dil belirtiminin parçası ve gerçekleştirimden gerçekleştirime değişmiyor. Aynı kural
D bölümünde de görülüyor: `obekte`, kendisinden sonra bildirilen `liste`den önce bitiyor.

Bu sıra rastgele değil; kapsamda açılan en son bağlamanın en önce bitmesi, iç içe geçmiş
kaynakların (bir dosyanın açtığı bir bağlantı gibi) her zaman açılış sırasının tersiyle
kapanmasını garanti ediyor. Kaynak koda bakan biri, bir kapsamdaki bitiş sırasını koşum
yapmadan, yalnız bildirim sırasını tersine çevirerek söyleyebiliyor.

Bu güvence yalnız bir sıralama ayrıntısı değil, bir bağımlılık düzeni de kuruyor. Bir
kapsamda ikinci bağlanan bir değer, ilk bağlanan bir değere ait bir kaynağı paylaşıyorsa —
örneğin aynı defteri kendi alanında tutuyorsa — bu ikinci değerin ilk değerden önce bitmesi
gerekiyor; aksi hâlde bitiş sırasında elindeki kaynak zaten kapanmış olurdu. Bildirim
sırasının tersine çevrilmesi tam olarak bunu sağlıyor: en son açılan, elindeki bağımlılıkları
hâlâ canlıyken bitiyor. `omur.rs` çekirdeğinde bu bağımlılık `defter`in kendisi — her `Iz`
değeri kendi `defter` alanını tutuyor ve bu alan, `Iz` değerinin kendisinden sonra değil,
tam olarak onunla birlikte bitiyor.

#### Özet

- Bir değerin ömrü dört biçimden birinde bitiyor: kapsam sonu, taşındığı yerde, açık
  çağrıda, kabıyla birlikte; on dört değerin 6'sı kapsam sonunda, 3'ü taşındığı yerde, 1'i
  açık çağrıda, 4'ü kabıyla birlikte bitti.
- Gölgeleme bir bitiş değildir; aynı ada yeniden bağlanmak eski bağlamanın ömrünü
  kısaltmaz.
- Bir değerin yığıtta mı öbekte mi yaşadığı tipten okunur (`Iz` ile `Box<Iz>` farkı);
  nerede yaşadığı, ne zaman bittiğinden ayrı bir sorudur.
- Kapsam sonunda biten değerler her zaman bildirimin tersi sırayla bitiyor; bu dilin
  sözüdür, ölçüm aracının seçimi değil.

#### Sonraki Adım

Bu derste bir değerin ömrünün nerede bittiği dört sınıfa ayrıldı ve kapsam sonunun kendi
sırası ölçüldü. Geriye kalan üç sınıftan en yaygını — taşındığı yerde — henüz yalnız üç
örnekle görüldü. Sıradaki ders bu sınıfı derinleştiriyor: sahiplik bir yerden başka bir
yere geçtiğinde bitiş noktasına tam olarak ne oluyor ve üç ayrı taşıma biçimi (işleve, iç
kapsama, yapı alanına) neden hep aynı sonuca varıyor.

### Sahiplik ve Taşıma

Source: https://academia.sh/tr/kurslar/sahiplik/sahiplik-ve-tasima

Bir değerin işleve, iç kapsama ve yapı alanına taşınmasının üçü de aynı sınıfa (taşındığı yerde) giriyor ve üçünde de değer tam olarak bir kez bitiyor; taşımadan sonra eski bağlamanın kullanılamaması derleyicinin derleme zamanında sınadığı bir kural, yeni sahip ise değeri sorunsuz kullanabiliyor.

Önceki ders bir değerin kapsam sonunda nasıl bittiğini ölçtü ve taşındığı yerde sınıfına yalnız
üç örnekle değindi. Bu ders o sınıfı derinleştiriyor: sahiplik bir yerden başka bir yere
geçtiğinde bitiş noktasına tam olarak ne oluyor? Eşzamanlılık kursunun (M09/K03) sorduğu "bir
goroutine nasıl duracak" sorusu buna benzer görünse de ayrıdır: orada koşan bir birim durur,
burada bir değer biter.

Programlama Temelleri kursu (M01/K02) bir değerin bir işleve nasıl geçtiğini — değerle
aktarım — kavram olarak kurmuştu; o kursta bu aktarım biçimi Python üzerinden anlatılmış,
işleve geçen bir değerin çağıranın elindeki adı etkilemediği gösterilmişti. Bu derste
ölçülen, Rust'ın aynı sözdizimine (bir değeri bir işleve argüman olarak yazmak) tamamen
farklı bir anlam yüklemesi: bir işleve geçen bir değer, artık işlevin de sahibi olur ve
çağıranın elindeki ad geçerliliğini yitirir. Bu sahiplik değişimi derleme zamanında
sınanıyor, çalışma zamanında değil. Bir değerin bir referans üzerinden, sahiplik vermeden
erişilmesi ayrı bir yol — o yol Ödünç Alma dersinde ele alınacak.

#### Üç Taşıma Biçimi

Aynı sınıfa (taşındığı yerde) üç ayrı yoldan girilebiliyor. Bir değer bir **işleve**
argüman olarak geçirilebilir; bir değer aynı kapsamın içinde açılan bir **iç kapsamda**
yeni bir ada yeniden bağlanabilir; bir değer bir **yapının alanına** konabilir. Üçünde de
ortak olan şey, eski bağlamanın artık değeri tutmuyor olması — değer aynı kalıyor, yalnız
ona hangi adın eriştiği değişiyor.

**SK4.** Bir değerin iç kapsamda yeni bir ada bağlanması (`let yeni_sahip = ic;`), önceki
dersteki gölgelemeyle karıştırılmamalı. Gölgeleme aynı ad üzerinde **yeni bir değer**
yaratıyordu ve eskisi kendi kapsam sonuna kadar ayrıca yaşıyordu. Burada tam tersi
oluyor: **aynı değer**, farklı bir ada taşınıyor ve eski ad bir daha o değere erişemiyor.
İkisi de bir "yeniden bağlama" gibi görünse de, biri yeni bir ömür başlatıyor, öbürü var
olan bir ömrün sahibini değiştiriyor.

Üç biçim farklı sözdizimleriyle görünse de aynı tek düzeneğin üç kullanım yeridir: Rust'ta
bir değeri `Copy` işaretli olmayan bir tipte herhangi bir yere yazmak — bir parametreye, bir
değişkene, bir alana — o değeri oradan oraya **taşır**. Söz dizimi hep aynı görünüyor
(`=` işareti, bir çağrı), ama arkasındaki anlam her seferinde aynı: eski konumdaki bit
kalıbı yeni konuma taşınıyor ve eski konum artık geçerli sayılmıyor. Bu derste üç ayrı
yerin (parametre, iç kapsam bağlaması, yapı alanı) hepsinin bu tek düzeneğe indirgendiği
ölçülüyor — üç farklı kural değil, bir kuralın üç görünümü.

Üç biçim pratikte de farklı tasarım kararlarına karşılık geliyor. Bir değeri işleve
taşımak, işlevin o değer üzerinde son söz sahibi olmasını istediğinde tercih ediliyor —
işlev bitince değer de bitiyor, çağıran tarafın onunla bir daha işi olmuyor. Bir değeri iç
kapsamda yeniden bağlamak, aynı değeri farklı bir isimle, genellikle daha dar ve geçici bir
işlem için tutmak istendiğinde görülüyor. Bir değeri bir yapının alanına koymak ise değeri
kalıcı olarak daha büyük bir bütünün parçası yapıyor — bundan sonra değerin ömrü, kendi
kapsamına değil, o yapının ömrüne bağlanıyor. Üçü de aynı düzeneği kullanıyor, ama hangi
birimin (işlev, kapsam, yapı) değerin yeni sınırını çizeceğine göre seçiliyor.

Bu seçim çoğu zaman veri modelinin kendisinden çıkıyor. Bir kayıt işleyen bir program,
kaydı doğrulayan bir işleve taşıyorsa (işleve taşıma), doğrulama bitince kaydın orada
kalmasını bekliyordur — çağıran taraf zaten kaydı bir daha kullanmayacaktır. Aynı program
bir kaydı geçici olarak dönüştürülmüş bir biçimde tutmak istiyorsa (iç kapsama taşıma),
dönüşüm yalnız o dar kapsamda geçerli kalıyor. Bir kayıt kalıcı bir yapının (örneğin bir
listenin ya da bir önbelleğin) parçası olacaksa (yapı alanına taşıma), sahiplik baştan o
yapıya veriliyor. Üç biçim arasında seçim, kod yazarken "bu değer artık kime ait olacak"
sorusuna verilen yanıtla belirleniyor.

#### Ölçümün Kesiti

Önceki dersin çekirdeğinden yalnız `Iz`, `Drop` uygulaması ve gözlem defteri kesiti
alınıyor; A, C, D bölümlerine bu derste ihtiyaç yok. Yardımcı kısım ayrı bir dosyaya
konuyor ki üç taşıma biçimi tek bir akışta yan yana görülebilsin.

Yardımcı dosya kendi başına derlenmiyor — `iz.rs` dosyasında bir giriş noktası yok, bu
yüzden çalıştırılamıyor, yalnız çalışma dizinine yazılıyor. `tasima.rs` dosyasının en
başındaki `mod iz;` satırı bu dosyayı asıl derlemenin içine çekiyor; `use iz::{Iz,
yeni_defter, okunan};` ise oradan hangi adların doğrudan kullanılacağını belirtiyor. `Iz`
yapısının `ad` alanı ve `yeni`/`yeni_defter`/`okunan` işlevleri modülün dışından
erişilebilmesi için `pub` işaretli; `defter` alanı ise işaretli değil, çünkü ona yalnız
`Iz`in kendi yöntemleri erişiyor. Görünürlüğün bu şekilde tek tek işaretlenmesi Kurulum ve
Paket Yöneticisi dersinde (M10/K01) zaten kurulmuştu; burada yalnız bir uygulaması var.

```rust
// iz.rs — bir degerin bitisini kaydeden olcum yardimcisi
use std::cell::RefCell;
use std::rc::Rc;

pub type Defter = Rc<RefCell<Vec<String>>>;

pub struct Iz {
    pub ad: String,
    defter: Defter,
}

impl Iz {
    pub fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz { ad: ad.to_string(), defter: Rc::clone(defter) }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

pub fn yeni_defter() -> Defter {
    Rc::new(RefCell::new(Vec::new()))
}

pub fn okunan(defter: &Defter) -> Vec<String> {
    defter.borrow().clone()
}
```

```rust
// tasima.rs — uc tasima bicimi: isleve, ic kapsama, yapi alanina
mod iz;
use iz::{Iz, yeni_defter, okunan};

struct Kutu {
    icerik: Iz,
}

fn yut(alinan: Iz) {
    println!("islev icinde okunan ad: {}", alinan.ad);
}

fn main() {
    let defter = yeni_defter();

    let tasinan = Iz::yeni("islev-icine", &defter);
    yut(tasinan);
    println!("islev donduktan sonra defter: [{}]", okunan(&defter).join(", "));

    let ic = Iz::yeni("ic-kapsama", &defter);
    {
        let yeni_sahip = ic;
        println!("ic kapsamda okunan ad: {}", yeni_sahip.ad);
    }
    println!("ic kapsam bittikten sonra defter: [{}]", okunan(&defter).join(", "));

    let alan = Iz::yeni("yapi-icine", &defter);
    {
        let kutu = Kutu { icerik: alan };
        println!("yapi alaninda okunan ad: {}", kutu.icerik.ad);
    }
    println!("yapi kapsami bittikten sonra defter: [{}]", okunan(&defter).join(", "));

    let kayitlar = okunan(&defter);
    println!();
    println!("toplam kayit: {}", kayitlar.len());
    for ad in ["islev-icine", "ic-kapsama", "yapi-icine"] {
        let adet = kayitlar.iter().filter(|k| k.as_str() == ad).count();
        println!("{:<14}{} kayit", ad, adet);
    }
}
```

```
islev icinde okunan ad: islev-icine
islev donduktan sonra defter: [islev-icine]
ic kapsamda okunan ad: ic-kapsama
ic kapsam bittikten sonra defter: [islev-icine, ic-kapsama]
yapi alaninda okunan ad: yapi-icine
yapi kapsami bittikten sonra defter: [islev-icine, ic-kapsama, yapi-icine]

toplam kayit: 3
islev-icine   1 kayit
ic-kapsama    1 kayit
yapi-icine    1 kayit
```

Üç satır da aynı düzeni izliyor: değer önce yeni sahibinde **okunuyor** (`alinan.ad`,
`yeni_sahip.ad`, `kutu.icerik.ad`), sonra yeni sahibin kendi kapsamı kapanınca deftere
düşüyor. `yut` işlevinin gövdesi bitince `islev-icine` hemen deftere yazılıyor — işlevin
kendi kapsamı, taşınan değerin yeni ve son kapsamı oluyor. İç kapsamdaki `yeni_sahip` ve
yapı alanındaki `kutu.icerik` için de aynı şey geçerli: ikisi de kendi dar kapsamları
kapanır kapanmaz bitiyor, dış kapsamın kapanmasını beklemiyor.

Erişim biçimi de üç formda farklılaşıyor. İşleve taşınan değere doğrudan parametre adıyla
ulaşılıyor (`alinan`), iç kapsama taşınan değere yeni bağlamanın adıyla (`yeni_sahip`), ama
yapı alanına taşınan değerin artık kendi başına bir adı yok — yalnız `kutu.icerik` yoluyla,
sahibi olan yapı üzerinden erişilebiliyor. Bu üçüncü biçim, taşımanın yalnız "bir değişkeni
başka bir değişkene kopyalamak" olmadığını gösteriyor: değer bir yapının **parçası**
hâline geldiğinde kendi bağımsız adını kaybediyor, artık yalnız kendisini saran yapının
alan yolu üzerinden görünüyor.

#### Eski Bağlamanın Kullanılamaması

Kod bu üç taşımadan sonra eski adı (`tasinan`, `ic`, `alan`) bir daha okumuyor — çünkü
okuyamaz. `yut(tasinan)` çağrısından sonra `tasinan.ad`'a erişmeye çalışan bir satır
eklenseydi, derleyici bunu reddederdi: sahiplik `yut`un parametresine geçti ve `tasinan`
artık geçerli bir değere işaret etmiyor. Aynı kural `ic` ve `alan` için de geçerli.

**SK5.** Bu redd bir çalışma zamanı hatası değil, derleme zamanında sınanan bir kuraldır.
Taşınmış bir adı yeniden okumaya çalışan bir kaynak hiç derlenmez; program hiçbir zaman bu
satıra ulaşmaz, bu yüzden yanlış kullanım çalışma zamanında hiçbir maliyete yol açmaz. Bu,
kabul edilen yazımın (yukarıdaki üç blok) neden hiçbir yerde eski adı tekrar okumadığını da
açıklıyor — doğru yazım zaten bu kısıtın içinde kalıyor.

Bu ret, önceki dersteki tek sahip gözlemiyle aynı yerden geliyor: bir değere aynı anda iki
ayrı adın erişebilmesi, o değerin hangi adın kapsamı kapanınca biteceğini belirsizleştirirdi.
Derleyici bunu, taşıma anında eski adı **geçersiz** sayarak önlüyor — eski ad hâlâ kaynakta
duruyor, ama bir daha kullanılamıyor.

Bu kısıtın neyi önlediğini somutlaştırmak için bir zihin deneyi yeterli: `tasinan` taşımadan
sonra da geçerli kalsaydı, hem `tasinan` hem `alinan` aynı `Iz` örneğine erişebilirdi. İkisi
de kendi kapsamı kapanınca bu örneği bitirmeye çalışırdı ve aynı değer iki kez bitirilmiş
olurdu — `defter`e aynı ad iki kez yazılırdı. Derleyici bu durumu hiç doğurmuyor; taşıma
anında yalnız bir adın geçerli kaldığından emin oluyor, geri kalanı (bitişin ne zaman
olacağı) önceki dersin kurallarına bırakıyor.

#### Taşıma Zincirlenebilir

Üç biçim tek bir taşımayı gösterdi, ama taşıma art arda da olabilir: bir değer bir işleve
girip oradan başka bir işleve, hatta geri çağırana devredilebilir. Aşağıdaki örnek aynı
`Iz` değerinin iki ayrı işlev sınırını geçip üçüncü bir kapsamda bitmesini ölçüyor.

```rust
// zincir.rs — tasima zincirlenebilir: sahiplik bir islevden digerine devredilebilir
mod iz;
use iz::{Iz, yeni_defter, okunan};

fn ikinci_asama(deger: Iz) -> Iz {
    println!("ikinci asamada okunan ad: {}", deger.ad);
    deger
}

fn ilk_asama(deger: Iz) {
    let devredilen = ikinci_asama(deger);
    println!("ilk asamaya donen ad: {}", devredilen.ad);
}

fn main() {
    let defter = yeni_defter();
    let deger = Iz::yeni("zincirli", &defter);
    ilk_asama(deger);
    println!("zincir bittikten sonra defter: [{}]", okunan(&defter).join(", "));
}
```

```
ikinci asamada okunan ad: zincirli
ilk asamaya donen ad: zincirli
zincir bittikten sonra defter: [zincirli]
```

`deger` burada dört ayrı adın elinden geçiyor: `main`'deki `deger`, `ilk_asama`'nın
parametresi, `ikinci_asama`'nın parametresi ve `ikinci_asama`'nın döndürdüğü değeri
tutan `devredilen`. Her geçiş bir taşıma ve her taşımadan sonra bir önceki ad artık
geçersiz. Zincirin sonunda değer `devredilen`e ait ve `ilk_asama`nın gövdesi bitince orada
bitiyor — `main`de değil. Dört ad, tek bir değer, tek bir bitiş: defterde yalnız
`zincirli` görünüyor, kaç kez taşındığından bağımsız olarak.

Bu, "taşındığı yerde" sınıfının neden bir sayıyla değil bir **konumla** tanımlandığını
gösteriyor. Değerin kaç kez el değiştirdiği önemli değil; ölçülen şey yalnız son sahibin
kapsamı. `ikinci_asama`nın değeri geri döndürmesi de bir taşımadır — dönüş değeri, çağıran
tarafın yeni bir bağlamasına taşınıyor; bu yüzden `devredilen` de kendi payına düşen bir
taşımanın sonucu.

Bir işlevin sahip olduğu bir değeri geri döndürmesi, bu kursta tekrar karşılaşılacak bir
düzen. Bir işlev kendi içinde kurduğu ya da parametre olarak aldığı bir değeri çağırana
geri vermek istediğinde, seçenek bir referans değil bir **sahiplik devri** oluyor — değer
işlevin dönüş tipi olarak yazılıyor ve dönüş, kendi başına bir taşıma sayılıyor. Bu düzen,
Ödünç Denetleyicisi dersinde bir işlevin kendi içinde kurduğu bir değere referans
döndürmesinin neden reddedildiğini anlamak için de gerekiyor: reddedilen tam olarak bu —
referans döndürmek; kabul edilen ise burada görülen — değerin kendisini döndürmek.

#### Sınırlayıcı Ölçüm: Taşıma Bir Kopyalama Değildir

Çıktının son üç satırı bunu doğrudan gösteriyor: `islev-icine`, `ic-kapsama` ve
`yapi-icine` adlarının üçü de defterde tam olarak **bir** kez geçiyor. Değer üç ayrı adı
sırayla taşısaydı bile (burada olmuyor, ama farz edelim), her taşıma bir kopya
oluşturmuyor — aynı `Iz` örneği, aynı bellek konumu, yalnız erişim adı değişiyor.

**SK6.** Üç taşıma biçiminin üçü de defterde tam olarak bir kayıt üretti; bu, aynı değerin
iki kez bitirilmeye çalışılmasının kaynak düzeyinde imkânsız olduğunu gösteriyor. Sahiplik
her zaman tek bir adda durduğu için bitiş noktası da her zaman tek bir yerde tetikleniyor —
taşıma bu tekliği bozmuyor, yalnız hangi adın sorumlu olduğunu değiştiriyor.

Taşımanın ömrü **kısaltmadığı** da aynı ölçümden okunuyor. `islev-icine` taşınmadan önce de,
taşındıktan sonra da aynı `Iz` örneği; taşıma bir yeniden oluşturma değil, bir yeniden
adlandırma. Önceki derste görülen dört sınıftan "taşındığı yerde" bu yüzden kendi başına bir
sınıf: değer ne kapsam sonunu bekliyor ne de açık bir çağrı alıyor, yalnız sahibinin kendi
sonunu miras alıyor.

Karşıt durumu düşünmek farkı netleştiriyor. `Iz` değerleri `Clone` uygulasaydı ve üç satır
`yut(tasinan.clone())`, `let yeni_sahip = ic.clone();` biçiminde yazılsaydı, defterde altı
kayıt olurdu: özgün üç değer kendi kapsamlarında, üç kopya da kendi kapsamlarında ayrı ayrı
biterdi. Bu derste `clone` hiç çağrılmadı — taşıma yeni bir `Iz` örneği kurmuyor, var olanı
elden ele geçiriyor. Defterin üç kaydı, altı değil, bu farkın doğrudan kanıtı.

Bu fark yalnız kayıt sayısında değil, işin niteliğinde de görünüyor. Bir kopyalama, kopyanın
kendi verisini ayrıca kurmayı gerektiriyor — `Iz`in durumunda yeni bir `String` ayırmayı;
taşıma ise var olan veriye yeni bir sahip atamaktan ibaret, hiçbir yeni ayırma yapmıyor.
Zincirleme örnekte görülen dört el değiştirme de bu yüzden tek bir `String` üzerinde
gerçekleşti — dört ayrı kopya değil, aynı verinin dört ayrı sahibi.

#### Özet

- Bir değer üç yoldan taşınabilir — işleve, iç kapsama, yapı alanına — ve üçü de aynı
  sınıfa (taşındığı yerde) giriyor.
- Taşınan değer yeni sahibinde kullanılabiliyor; eski ad ise taşımadan sonra bir daha
  okunamıyor, çünkü artık geçerli bir değere işaret etmiyor.
- Eski adın kullanılamaz hâle gelmesi derleme zamanında sınanan bir kuraldır; çalışma
  zamanında hiçbir maliyeti yok.
- Taşıma bir kopyalama değildir: defterde her değer için tam olarak bir kayıt oluşuyor,
  aynı değer iki kez bitirilmeye çalışılmıyor.
- Taşıma zincirlenebilir — bir değer birden çok işlev sınırını art arda geçebilir — ama
  kaç kez el değiştirirse değiştirsin, sonunda yalnız bir bitiş noktası oluyor.

#### Sonraki Adım

Bu üç taşıma biçiminin ortak noktası, eski adın değeri kaybetmesiydi — sahiplik her
seferinde tam olarak bir yerden bir yere gitti. Sıradaki soru bunun tam tersini
araştırıyor: bir değere, sahipliği hiç vermeden erişmek mümkün mü? Ödünç Alma dersi, bir
değeri ödünç veren adın değeri kaybetmediğini ve ödünç alınan değerin ödünç sırasında
hiçbir yere bitmediğini ölçüyor — taşımanın aksine, burada eski sahip hâlâ sahip kalıyor.

### Ödünç Alma

Source: https://academia.sh/tr/kurslar/sahiplik/odunc-alma

Bir değer sahipliği hiç vermeden bir referans üzerinden okunabilir ve yazılabilir: ödünç sürerken defterde hiçbir kayıt oluşmaz, ödünç kapsamı kapandığında değer hâlâ sahibinde erişilebilir durumdadır. Paylaşımlı ve değiştirilebilir referans birbirini dışlar; bir referansın kapsamı, kaynağın kapsamının her zaman içinde kalmak zorundadır.

Önceki ders sahiplik devrettiğinde bitiş noktasının nasıl taşındığını ölçtü — taşınan değerin
eski adı geçerliliğini kaybediyordu. Bu ders sahiplik hiç devredilmeden bir değere nasıl
erişildiğini ölçüyor: ödünç alma. Soru şu: bir değeri ödünç veren ad değeri kaybediyor mu ve
ödünç alınan değer ödünç sürerken bir yere bitiyor mu? Eşzamanlılık kursunun (M09/K03) "bir
goroutine nasıl duracak" sorusuyla karışmaz: orada koşan bir birim durur, burada bir değer
biter.

Önceki dersin son bölümü, bir değerin bir işleve tek yönlü ve geri dönüşsüz taşınabileceğini
gösterdi — ya da sahip zincir boyunca değişse de değer sonunda mutlaka bir yerde bitti. Bu
ders aynı işlevlere geçen değerlerde farklı bir yol açıyor: bir değeri hiç taşımadan, yalnız
ona geçici bir erişim vererek de aynı işi yapabiliyoruz. İki yol da geçerli, ama sonuçları
kaynakta ayrı ayrı okunabiliyor.

Programlama Temelleri kursu (M01/K02) bir değerin bir işleve referans olarak nasıl geçtiğini
kavram olarak kurmuştu. Bu derste ölçülen, Rust'ın bu geçişi iki ayrı, birbirini dışlayan
biçime ayırması — **paylaşımlı** ve **değiştirilebilir** referans — ve bu ayrımı derleme
zamanında sınaması.

#### Ödünç Almak Sahiplik Vermek Değildir

Bir referans (`&T` ya da `&mut T`), işaret ettiği değerin sahibi değildir; yalnız o değere
erişim sağlayan ayrı, küçük bir değerdir. Referansın kendisinin de bir kapsamı var ve o
kapsam kapandığında referans biter, ama referansın bitmesi işaret ettiği değeri
**etkilemez** — çünkü referans zaten o değerin sahibi olmamıştı, kapsamı kapanırken
`Drop`'u tetikleyecek bir şeyi yoktur.

Rust iki tür referansı ayırıyor. **Paylaşımlı referans** (`&T`) aynı değere aynı anda
birden çok kez alınabilir ve yalnız okumaya izin verir. **Değiştirilebilir referans**
(`&mut T`) aynı anda yalnız bir tane olabilir ve değeri okumanın yanında değiştirmeye de
izin verir. İkisi aynı anda, aynı değer için bir arada bulunamaz.

Bu iki tür bir seçenek değil, bir zorunluluk. Bir değere erişmek isteyen her kod parçası —
bir işlev parametresi, bir yerel bağlama, bir yapı yöntemi — hangi türü istediğini önceden
söylemek zorunda; söz dizimindeki tek fark bir `mut` anahtar sözcüğü olsa da, ürettiği
yetki tamamen farklı. Bu ayrım kaynakta görünür olduğu için, bir okuyucu bir referansın
değeri değiştirip değiştiremeyeceğini, o referansın alındığı satıra bakarak söyleyebiliyor
— değerin kendi tanımına ya da nasıl kullanıldığına bakmadan.

**SK7.** Bir referans kendi başına bir değerdir ve kendi kapsamı vardır, ama `Iz` gibi
`Drop` uygulayan bir tipin referansı `Drop`'u uygulamaz. `&Iz` ya da `&mut Iz` tipinde bir
değer kapsamının sonunda sessizce yok olur; deftere hiçbir şey yazmaz, çünkü yazma işini
yapan kod yalnız `Iz`in kendi `drop` yönteminde ve o yöntem yalnız sahip olunan bir `Iz`
bittiğinde çağrılır.

Bu ayrım önceki dersle doğrudan karşıtlık kuruyor. Sahiplik ve Taşıma dersinde bir işleve
geçirilen `Iz` değeri, işlevin parametresine **taşınıyordu** — işlev bitince değer de
bitiyordu ve aynı değeri ikinci bir çağrıya geçirmek mümkün değildi, çünkü ilk çağrıdan
sonra eski ad geçersiz kalıyordu. Bir işlev değeri ödünç alıyorsa bu kısıt ortadan
kalkıyor: işlev değeri kullanıp bırakıyor, sahiplik hiç el değiştirmiyor, çağıran taraf
aynı değeri istediği kadar tekrar kullanabiliyor.

Bu dersin bütün ölçümleri önceki dersin çekirdeğinden aynı kesiti kullanıyor — `Iz`, `Drop`
uygulaması ve gözlem defteri; yardımcı kısım ayrı bir dosyaya konuyor ki sonraki örnekler
onu tekrar tekrar `mod` ile çekebilsin.

```rust
// iz.rs — bir degerin bitisini kaydeden olcum yardimcisi
use std::cell::RefCell;
use std::rc::Rc;

pub type Defter = Rc<RefCell<Vec<String>>>;

pub struct Iz {
    pub ad: String,
    defter: Defter,
}

impl Iz {
    pub fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz { ad: ad.to_string(), defter: Rc::clone(defter) }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

pub fn yeni_defter() -> Defter {
    Rc::new(RefCell::new(Vec::new()))
}

pub fn okunan(defter: &Defter) -> Vec<String> {
    defter.borrow().clone()
}
```

```rust
// odunc_islev.rs — bir islevin degeri odunc alip iade etmesi, tasima ile karsitligi
mod iz;
use iz::{Iz, yeni_defter, okunan};

fn oku(referans: &Iz) -> usize {
    referans.ad.len()
}

fn main() {
    let defter = yeni_defter();
    let deger = Iz::yeni("paylasilan", &defter);

    let uzunluk1 = oku(&deger);
    let uzunluk2 = oku(&deger);
    println!("ilk okuma: {}, ikinci okuma: {}", uzunluk1, uzunluk2);
    println!("iki cagridan sonra defter: [{}]", okunan(&defter).join(", "));
}
```

```
ilk okuma: 10, ikinci okuma: 10
iki cagridan sonra defter: []
```

`oku` işlevi `deger`i iki kez, art arda ödünç alıyor. Sahiplik ve Taşıma dersindeki `yut`
işlevi aynı değeri ikinci kez alacak bir çağrıyla derlenemezdi, çünkü ilk çağrı zaten
sahipliği tüketmişti. Burada iki çağrı da geçerli, çünkü `oku` hiçbir zaman sahiplik
istemiyor — parametre tipi `&Iz`, `Iz` değil. İki çağrıdan sonra bile defter boş: `deger`
`main`in sonuna kadar sahibinde yaşamaya devam ediyor.

`oku(&deger)` çağrısındaki `&` işareti burada zorunlu — işlev bir referans istiyor, kaynak
bunu açıkça vermek zorunda. Kodun başka yerlerinde (`a.ad`, `deger.ad`) aynı zorunluluk
görünmüyor: bir alana `.` ile erişmek ya da bir yöntem çağırmak, gerektiğinde derleyici
tarafından örtük olarak ödünç alınıyor. `referans.ad.len()` satırı da böyle — `referans`
zaten bir `&Iz`, ama `.ad` erişimi ile `.len()` çağrısı ayrı bir `&` yazmayı gerektirmiyor.
Örtük ödünç alma yalnız kaynağın okunabilirliğini kolaylaştırıyor; sınırları (paylaşımlı mı
değiştirilebilir mi, ne kadar sürüyor) aynı kurallara tabi.

#### Ölçüm: Ödünç Sürerken Defter Boş

Aşağıdaki ölçüm üç kapsam seviyesini iç içe koyuyor: en dışta `main`, onun içinde `deger`in
kendi sahiplik kapsamı, onun içinde de sırayla paylaşımlı ve değiştirilebilir ödünç
kapsamları. Yardımcı dosya (`iz.rs`) zaten çalışma dizininde; bu blok onu tekrar `mod iz;`
ile çekiyor.

```rust
// odunc.rs — odunc alinan deger, odunc surerken hicbir yere bitmiyor
mod iz;
use iz::{Iz, yeni_defter, okunan};

fn main() {
    let defter = yeni_defter();

    {
        let mut deger = Iz::yeni("odunc-1", &defter);

        {
            let a = &deger;
            let b = &deger;
            println!("paylasimli okuma: {} ve {}", a.ad, b.ad);
            println!("odunc surerken defter: [{}]", okunan(&defter).join(", "));
        }
        println!("paylasimli odunc bittikten sonra defter: [{}]", okunan(&defter).join(", "));

        {
            let m = &mut deger;
            m.ad.push_str("-not");
            println!("degistirilebilir odunc icinde ad: {}", m.ad);
        }
        println!("degistirilebilir odunc bittikten sonra defter: [{}]", okunan(&defter).join(", "));
        println!("deger hala erisilebilir, kendi adi: {}", deger.ad);
    }
    println!("dis kapsam bittikten sonra defter: [{}]", okunan(&defter).join(", "));
}
```

```
paylasimli okuma: odunc-1 ve odunc-1
odunc surerken defter: []
paylasimli odunc bittikten sonra defter: []
degistirilebilir odunc icinde ad: odunc-1-not
degistirilebilir odunc bittikten sonra defter: []
deger hala erisilebilir, kendi adi: odunc-1-not
dis kapsam bittikten sonra defter: [odunc-1-not]
```

Beş ayrı ölçüm noktasının dördü defterin boş olduğunu gösteriyor — paylaşımlı ödünç
sürerken, paylaşımlı ödünç bittikten sonra, değiştirilebilir ödünç sürerken (satır kendi
içinde basıldığı için ayrıca görünmüyor ama bir sonraki satır bunu doğruluyor) ve
değiştirilebilir ödünç bittikten sonra. `deger` yalnız en dıştaki kapsam (`main`'in kendi
gövdesi) kapandığında bitiyor ve defter ancak o zaman `odunc-1-not` yazısını alıyor. `a`
ve `b`nin ikisinin de aynı anda var olabilmesi — ikisi de `deger`i yalnız okuyor, birbirine
karışmıyor — paylaşımlı referansın çoğulluğunu gösteriyor.

Çıktıdaki son satır (`odunc-1-not`) bunun da ötesinde bir şey kanıtlıyor: `deger`in kendisi
hiçbir zaman yeniden oluşturulmadı. `m` üzerinden yapılan değişiklik, `deger`in kendi
`ad` alanına yazıldı; `deger` bittiğinde deftere düşen isim, oluşturulduğu andaki
`odunc-1` değil, ödünç sırasında değiştirilmiş hâli. Bu, ödünç almanın salt-okunur bir
görüntü değil, gerçek bir erişim yolu olduğunu gösteriyor — paylaşımlı referans yalnız
okurken, değiştirilebilir referans kaynağın kendisini kalıcı olarak değiştirebiliyor.

#### Paylaşımlı ve Değiştirilebilir Referans

`m.ad.push_str("-not")` satırı, değiştirilebilir bir referans üzerinden `deger`in kendi
alanını gerçekten değiştiriyor — bu satırdan sonra hem `m.ad` hem de kapsam kapandıktan
sonra okunan `deger.ad` yeni değeri (`odunc-1-not`) taşıyor. Paylaşımlı referanslarla
(`a`, `b`) bu mümkün değildi: `a.ad`'i değiştirmeye çalışan bir satır derleyici tarafından
reddedilirdi, çünkü `&T` yalnız okuma izni veriyor.

**SK8.** Paylaşımlı referansların aynı anda birden çok olabilmesi, hiçbirinin değeri
değiştirememesinden kaynaklanıyor — okuma birbirine karışmaz. Değiştirilebilir bir
referansın aynı anda yalnız bir tane olabilmesi ise tam tersi bir nedenden: bir değişiklik
başka bir okumanın ya da başka bir değişikliğin ortasında beklenmeyen bir sonuca yol
açabilir. Kural referansların **sayısına** değil, aralarında bir **değişikliğin var olup
olmadığına** bakıyor.

Bu ayrımın somut karşılığı, ödünç almanın kendisinin de iki ayrı yetki taşıması. `oku`
işlevi yalnız `&Iz` istediği için değeri değiştiremez — parametre tipinin kendisi bunu
engelliyor, işlevin gövdesine bakmaya bile gerek yok. Bir işlev değeri değiştirmek
istiyorsa parametresini `&mut Iz` olarak yazmak zorunda ve bu durumda o işlev aynı değere
aynı anda ödünç alınmış başka hiçbir referansla bir arada çağrılamıyor. Bu, bir işlev
imzasının yalnız hangi tipi aldığını değil, o tipe **ne yapabileceğini** de baştan
belirlediği anlamına geliyor — Rust'ın Tasarım Hedefleri dersinde (M10/K01) sınıfın imzadan
okunması gibi, burada da yetki imzadan okunuyor.

#### Redd: Aynı Anda Bir Yazan ya da Çok Okuyan

Yukarıdaki kod paylaşımlı ödünç ile değiştirilebilir ödüncü hep ayrı kapsamlarda, art arda
kullandı — hiçbir zaman ikisi birden aynı anda canlı olmadı. Bu tesadüf değil, zorunlu.
`a` ve `b` hâlâ kapsamdayken aynı satırlara `let m = &mut deger;` eklenseydi, derleyici
reddederdi: aynı değere aynı anda hem paylaşımlı hem değiştirilebilir bir referans birlikte
var olamaz. Aynı kural iki değiştirilebilir referans için de geçerli — `let m1 = &mut
deger;` ile `let m2 = &mut deger;` aynı kapsamda birlikte yaşayamaz, çünkü ikisi de aynı
alana yazma izni taşıyor ve hangi yazmanın önce, hangisinin sonra geçerli olacağı kaynaktan
okunamaz hâle gelirdi. İki paylaşımlı referans (`a` ve `b`) için bu sorun yok, çünkü
hiçbiri yazmıyor — okumanın sırası sonucu değiştirmiyor.

Bu ret bir çalışma zamanı denetimi değil; kaynak, iki referansın kapsamları çakıştığı an
hiç derlenmiyor. Kabul edilen yazım (yukarıdaki kod) bu çakışmayı zaten baştan dışlıyor:
paylaşımlı kapsam kendi süslü parantezleriyle kapanıyor, değiştirilebilir kapsam ondan
sonra ayrı süslü parantezlerle açılıyor — iki kapsam hiçbir noktada üst üste binmiyor.

Aynı kısıt işlev çağrılarında da geçerli. `oku(&deger)` iki kez art arda çağrılabildi,
çünkü hiçbir çağrının referansı bir sonraki çağrı başlarken hâlâ canlı değildi — her çağrı
kendi ödünç kapsamını açıp kendi içinde kapatıyor. Aynı değeri hem `oku`ya (`&Iz`) hem de
aynı anda değiştiren bir işleve (`&mut Iz`) birlikte geçirmeye çalışan bir yazım, iki
kapsam çakıştığı için derlenmezdi. Kural, tek bir işlevin gövdesiyle sınırlı değil; bir
kaynaktaki bütün referans kapsamları aynı denetime tabi.

#### Sınırlayıcı Ölçüm: Ödünç Ömrü Uzatmaz

Üç kapsam seviyesi (`main`, `deger`in kendi kapsamı, ödünç kapsamları) birbirinin içine
yerleşiyor ve bu yerleşim tek yönlü: bir ödünç kapsamı her zaman kaynağın kapsamının
**içinde** kalıyor, hiçbir zaman dışına taşmıyor. `a` ve `b`, `deger`in kapsamı kapanmadan
önce kendi kapsamlarını kapatıyor; `m` de öyle. Hiçbir referans, işaret ettiği değerden
daha uzun yaşamıyor.

**SK9.** Bir referansın geçerli olduğu aralık, kaynağının kapsamını hiçbir zaman aşamaz —
bu, ödünç almanın ömrü **uzatmadığının** somut karşılığı. `deger`in kendisi `main`in
gövdesi bitene kadar yaşıyor; içindeki hiçbir referans bundan daha uzun bir aralık talep
edemiyor, çünkü edebilseydi, o referans kaynağı zaten bitmiş bir değere işaret ederdi.

Bu kısıt burada iç içe kapsamlarla, doğal bir yazımla sağlandı: her ödünç kendi süslü
parantezleri içinde açılıp kapandı ve `deger`in kendi kapsamı bunların hepsini kapsadı.
Bir referansı bu iç içe geçmenin dışına, örneğin `deger`in kapsamından sonra hâlâ geçerli
olacak bir yere taşımaya çalışan bir yazım derleyici tarafından reddedilir — bu aralığın
kendi adı ve kuralları sıradaki bölümde ele alınacak.

Bu kısıtın neden zorunlu olduğu, tersini düşününce netleşiyor. `m` adlı değiştirilebilir
referans `deger`in kapsamından daha uzun yaşayabilseydi, `deger` bitip deftere yazıldıktan
**sonra** bile `m` üzerinden bir okuma ya da yazma denenebilirdi — ama artık işaret
edilecek geçerli bir `Iz` kalmamış olurdu. Derleyici bu senaryoyu, referansın geçerli
olduğu aralığı kaynağın kapsamıyla sınırlayarak baştan engelliyor. `oku` işlevindeki
`&Iz` parametresi de aynı kısıta tabi: işlev kendi gövdesi içinde bu referansı ne kadar
kullanırsa kullansın, referansın aralığı `oku` çağrısının süresini aşamıyor — çağıran
taraftaki `deger` hâlâ sahibinde, iki çağrının arasında bile referans yeniden alınıyor.

Bu derste ölçülen üç şey birbirine bağlı. Ödünç almak sahiplik vermediği için ödünç alınan
değer ödünç sürerken hiçbir yere bitmiyor; referansın kendisi kaynaktan ayrı, kendi
kapsamına sahip küçük bir değer olduğu için kaynağın bitişini tetiklemiyor; ve bir
referansın kapsamı kaynağın kapsamını hiçbir zaman aşamadığı için "hâlâ yaşayan bir
değere işaret etme" garantisi baştan kuruluyor. Paylaşımlı ve değiştirilebilir ayrımı bu
üç ölçümün üzerine binen dördüncü bir kısıt: aynı anda birden çok okuma güvenli, ama bir
değişiklik başka hiçbir erişimle aynı anda olamıyor. Sahiplik ve Taşıma dersindeki "tek
sahip" ilkesi burada "tek yazan, çok okuyan" biçiminde genişliyor — sahiplik hâlâ tek bir
adda, ama o adın izniyle birden çok geçici erişim aynı anda var olabiliyor. Bu genişleme,
sahibin kendisinin hiçbir zaman devre dışı kalmadığı anlamına da geliyor: `deger`, kaç
referans dağıtırsa dağıtsın, kendi kapsamı içinde tek gerçek sahip olarak kalmaya devam
ediyor.

#### Özet

- Bir referans, işaret ettiği değerin sahibi değildir; kendi kapsamı kapandığında yalnız
  kendisi biter, kaynağı etkilemez.
- Ödünç sürerken defterde hiçbir kayıt oluşmuyor; ödünç alınan değer, ödünç kapsamı
  kapandıktan sonra da sahibinde erişilebilir kalıyor. Ödünç verilen değerin ömrü **kapsam
  sonunda** bitiyor, ödünç bittiğinde değil.
- Paylaşımlı referans (`&T`) aynı anda birden çok olabilir ve yalnız okur; değiştirilebilir
  referans (`&mut T`) aynı anda yalnız bir tane olabilir ve değiştirebilir.
- Aynı değere aynı anda hem paylaşımlı hem değiştirilebilir, ya da iki değiştirilebilir
  referans birlikte var olamaz; bu kural derleme zamanında sınanır.
- Bir referansın kapsamı, kaynağının kapsamının her zaman içinde kalmak zorundadır —
  ödünç almak ömrü uzatmaz.
- Aynı değer, ödünç alan bir işleve arka arkaya birden çok kez geçirilebilir; bu, sahiplik
  isteyen bir işlevin (`yut` gibi) yalnız bir kez çağrılabilmesiyle doğrudan karşıt. Bir
  alana `.` ile erişmek ya da bir yöntem çağırmak da gerektiğinde örtük olarak ödünç alır.

#### Sonraki Adım

Bu derste bir değerin **tamamına** ödünç verilen referanslar ölçüldü — `&Iz` ya da
`&mut Iz`, hep bütün değere. Sıradaki ders aynı sahiplik-vermeden-erişim ilkesini bir
değerin yalnız bir **parçasına** uyguluyor: bir dizginin ya da bir büyüyen dizinin
belirli bir aralığını, kaynağı hiç bitirmeden nasıl görüntüleyebiliriz? Ödünç almanın
burada ölçülen bütün kuralları (kaynak bitmiyor, ömür uzamıyor, paylaşımlı/değiştirilebilir
ayrımı) aynen geçerli kalacak; değişen yalnız görüntülenen kısmın büyüklüğü.

### Dilimler

Source: https://academia.sh/tr/kurslar/sahiplik/dilimler

Bir dilim, sahiplik almadan bir dizginin ya da bir büyüyen dizinin belirli bir aralığını görüntüler: dilim kullanılır, dilim biter, ama kaynak hiç bitmez. Dilimin uzunluğu kaynaktan türer ve boş bir dilim geçerlidir; dilim yaşarken kaynak değiştirilemez, dilim bittikten sonra değişiklik sorunsuz geçer.

Önceki ders bir değerin **tamamına** ödünç verilen referansları ölçtü. Bu ders aynı
sahiplik-vermeden-erişim ilkesini bir değerin yalnız bir **parçasına** uyguluyor: dilim
(slice), bir dizginin ya da bir büyüyen dizinin ardışık bir aralığını, sahiplik almadan
görüntüleyen bir referans türü. Ölçülen yine bir değerin bitişidir, koşan bir birimin durması
değil — Eşzamanlılık kursunun (M09/K03) goroutine sorusu bu kursun ekseninin dışında kalıyor.

Dilim kavramının kendisi Eşzamanlılık kursunda (M09) zaten kurulmuştu — bir dizinin ardışık
bir alt aralığını temsil eden, kendi uzunluğunu taşıyan bir görünüm. Bu derste ölçülen,
Rust'ın dilimi bir aralık söz dizimiyle (`[baslangic..bitis]`) kurması ve önceki üç dersin
kurallarının (sahiplik alınmıyor, kaynak bitmiyor, ödünç ömrü kaynağı aşamıyor) buraya
aynen uygulanması.

Önceki üç ders bir referansın hep **tek bir değere** işaret ettiğini varsaydı: `&Iz`,
`&mut Iz`. Dilim bu varsayımı gevşetiyor — bir referans artık birden çok ardışık değere
birden işaret edebiliyor, ama bunu yaparken sahiplik, kapsam ve paylaşımlı/değiştirilebilir
kurallarının hiçbirini değiştirmiyor. Bu derste ölçülen, kuralların aynı kaldığı, yalnız
neyin ödünç alındığının değiştiği.

#### Bir Değerin Bir Parçasını Görüntülemek

Bir dilim, `&T`'nin bir çeşidi: `&[Iz]` bir büyüyen diziden alınan bir görünüm, `&str` bir
dizgiden alınan bir görünüm. İkisi de kaynağın kendi verisine işaret ediyor — veriyi
kopyalamıyor — ve kendi uzunluğunu ayrıca taşıyor. Bir dilim aldığında kaynağın sahibi
değişmiyor, yalnız o aralığa geçici bir erişim kuruluyor.

Aralık söz dizimi `[baslangic..bitis]` biçiminde: `baslangic` dahil, `bitis` hariç. En
basit hâliyle, sahiplenme sorusu hiç devreye girmeden, aralığın kendisi şöyle okunuyor.

```rust
// temel_dilim.rs — dilim sozdizimi: baslangic..bitis araligi
fn main() {
    let sayilar = [10, 20, 30, 40, 50];
    let orta = &sayilar[1..4];
    println!("kaynak: {:?}", sayilar);
    println!("dilim: {:?}", orta);
    println!("dilim uzunlugu: {}", orta.len());
}
```

```
kaynak: [10, 20, 30, 40, 50]
dilim: [20, 30, 40]
dilim uzunlugu: 3
```

`&sayilar[1..4]` indeks 1'den başlayıp indeks 4'e (dahil değil) kadar olan üç elemanı
görüntülüyor — `20`, `30`, `40`. `sayilar`'ın kendisi burada `i32` gibi kopyalanabilir bir
tip taşıdığı için sahiplik sorusu görünmüyor; asıl soru, kaynağın kendisi kopyalanamayan,
`Drop` uygulayan bir tip taşıdığında ortaya çıkıyor — tam da bu dersin geri kalanının
ölçtüğü durum. `[1..4]` yazımının kendisi `sayilar`ın türünü değiştirmiyor; `sayilar` hâlâ
sabit uzunluklu bir dizi, `orta` ise ayrı bir tip — belirli bir uzunluğu olmayan, kaynaktan
türeyen bir dilim.

#### Ölçüm: Kaynak Hiç Bitmez

Aşağıdaki ölçüm üç `Iz` değeri tutan bir büyüyen diziden ilk iki elemanı görüntüleyen bir
dilim alıyor, dilimi kullanıyor, dilimin kapsamını kapatıyor ve ardından kaynağı
değiştiriyor.

```rust
// iz.rs — bir degerin bitisini kaydeden olcum yardimcisi
use std::cell::RefCell;
use std::rc::Rc;

pub type Defter = Rc<RefCell<Vec<String>>>;

pub struct Iz {
    pub ad: String,
    defter: Defter,
}

impl Iz {
    pub fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz { ad: ad.to_string(), defter: Rc::clone(defter) }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

pub fn yeni_defter() -> Defter {
    Rc::new(RefCell::new(Vec::new()))
}

pub fn okunan(defter: &Defter) -> Vec<String> {
    defter.borrow().clone()
}
```

```rust
// dilim_omru.rs — dilim sahiplik almadan gorunturur, kaynagi bitirmez ama kilitler
mod iz;
use iz::{Iz, yeni_defter, okunan};

fn main() {
    let defter = yeni_defter();
    let mut liste = vec![
        Iz::yeni("bir", &defter),
        Iz::yeni("iki", &defter),
        Iz::yeni("uc", &defter),
    ];
    let once = okunan(&defter).len();

    {
        let goruntu = &liste[0..2];
        println!("dilim uzunlugu: {}, ilk ad: {}", goruntu.len(), goruntu[0].ad);
        println!("dilim yasarken defter: [{}]", okunan(&defter)[once..].join(", "));
    }
    println!("dilim bittikten sonra defter: [{}]", okunan(&defter)[once..].join(", "));

    liste.push(Iz::yeni("dort", &defter));
    println!("dilim bittigi icin liste degistirildi, uzunluk: {}", liste.len());
}
```

```
dilim uzunlugu: 2, ilk ad: bir
dilim yasarken defter: []
dilim bittikten sonra defter: []
dilim bittigi icin liste degistirildi, uzunluk: 4
```

`goruntu` yalnız `liste`nin ilk iki elemanını görüntülüyor, ama üç elemanın da sahibi hâlâ
`liste`. Dilim yaşarken de, dilimin kapsamı kapandıktan sonra da defter boş — `bir`, `iki`
ve `uc` değerlerinin hiçbiri bitmiyor, çünkü dilim onlara sahip olmadı, yalnız onlara
baktı. `liste`nin kendisi bu ölçümde hiç bitmiyor (kod dosyanın sonunda kapanmadığı için);
görülen tek bitiş, dilimin kendi kapsamının kapanması — ki bu da deftere hiçbir şey
yazmıyor, çünkü `&[Iz]` tipinde bir dilim `Drop` uygulamıyor.

Burada dikkat edilmesi gereken bir ayrıntı var: `goruntu` yalnız ilk iki elemanı (`bir`,
`iki`) görüntülüyor, üçüncü eleman (`uc`) dilimin dışında kalıyor. Buna rağmen ölçüm
`liste`nin tamamının hâlâ sahibinde durduğunu gösteriyor — dilimin kapsamadığı `uc` da,
kapsadığı `bir` ve `iki` de aynı şekilde etkilenmiyor. Dilim, kaynağın yalnız bir alt
kümesini **okumak** için bir pencere açıyor; kaynağın geri kalanının sahipliğine ya da
ömrüne hiçbir şekilde karışmıyor.

`goruntu[0].ad` erişimi de bunu somutlaştırıyor: `goruntu[0]` dilimin ilk elemanına
işaret eden bir `&Iz` üretiyor (sahiplik değil, yeni bir ödünç) ve `.ad` bu ödünç
üzerinden okunuyor. Aynı satırda üç ayrı ödünç iç içe geçmiş durumda — `liste`den
`goruntu`ya, `goruntu`dan `goruntu[0]`'a, `goruntu[0]`'dan `.ad`'a — ama hiçbiri
sahiplik istemiyor, hepsi aynı temel `Iz` değerlerine kadar geri gidiyor.

**SK10.** Bir dilim, aynı `&T` referansı gibi, işaret ettiği elemanların sahibi değil.
Kapsamı kapandığında yalnız kendisi (dilimin kendi `başlangıç, uzunluk` çifti) yok olur;
elemanların hiçbiri bundan etkilenmez. Önceki dersteki "referans kaynağı bitirmez" kuralı
burada aynen geçerli, yalnız görünürlük tek bir değer yerine ardışık bir aralık.

#### Sınırlayıcı Ölçüm: Dilim Kaynağı Kilitler

`liste.push(...)` satırı `goruntu`nun kapsamı kapandıktan **sonra** çalışıyor. Bu sıralama
zorunlu: `goruntu` hâlâ kapsamdayken aynı satır eklenseydi, derleyici reddederdi. `goruntu`
`liste`nin paylaşımlı bir ödüncü ve `push` çağrısı `liste`yi değiştirmek için
değiştirilebilir bir ödünç istiyor — Ödünç Alma dersinde kurulan "aynı anda bir yazan ya da
çok okuyan" kuralı burada da geçerli, yalnız ödünç aldığı şey artık bütün değer değil,
onun bir parçası.

**SK11.** Bir dilim kaynağının **tamamını** kilitliyor, yalnız görüntülediği aralığı değil.
`goruntu` yalnız ilk iki elemanı görüntülese de, `liste`nin herhangi bir yerine (örneğin
sona) eleman eklemeyi de engelliyor — çünkü bir ekleme büyüyen dizinin kendi iç düzenini
yeniden ayarlayabilir ve dilimin işaret ettiği konumları geçersiz kılabilir. Kısıt dilimin
kapsadığı elemanlarla sınırlı değil, kaynağın bütününe yayılıyor.

Bu, "dilim kaynağın yalnız bir parçasını görüntüler" cümlesiyle ilk bakışta çelişiyor
gibi görünebilir — görüntülenen parça küçük, ama kilitlenen yüzey büyük. Çelişki yok:
dilim yalnız kendi aralığındaki elemanları **okumaya** izin veriyor, ama kaynağın kendi
düzeninde (kaç eleman tuttuğu, elemanların nerede durduğu) herhangi bir değişiklik,
dilimin dayandığı varsayımı bozabileceği için, o değişiklik dilim yaşarken hiç
başlatılamıyor. Görüntülenen kısım dar, korunan varsayım geniş.

Kabul edilen yazım bu sırayı zaten koruyor: dilim önce kendi dar kapsamında kullanılıp
bırakılıyor, `push` ancak ondan sonra, `liste`ye tek başına erişimin olduğu bir noktada
çağrılıyor. Aynı işi ters sırayla yazmaya çalışmak — önce değiştirip sonra eski dilimi
okumaya devam etmek — derleyici tarafından hiç derlenmez.

Bu kısıtın neyi önlediği somut: `push` bir büyüyen dizinin arka planındaki depolama
alanını gerektiğinde yeniden ayırabilir — dizi büyürken bütün elemanlar yeni bir konuma
taşınabilir. `goruntu` eski konumlara işaret ediyor olsaydı ve `push` bu taşımayı
tetikleseydi, `goruntu` artık geçerli olmayan bir bellek bölgesine işaret ediyor olurdu.
Derleyici bu senaryoyu, dilim yaşarken kaynağı değiştiren hiçbir çağrıya izin vermeyerek
baştan kapatıyor — `push`un gerçekten yeniden ayırma yapıp yapmayacağını bilmesi bile
gerekmiyor, kural bütün değiştirici çağrılar için aynı.

Aynı kısıt tek bir eleman okumak için de geçerli: `liste[2]` gibi bir doğrudan indeksleme
`goruntu` kapsamdayken sorun çıkarmaz, çünkü o da yalnız okuyor — paylaşımlı iki ödünç bir
arada durabiliyor. Sorun yalnız bir **değişiklik** aynı anda talep edildiğinde başlıyor.

#### Dilim, Bir İşleve Kaynağı Taşımadan Geçirilir

Ödünç Alma dersindeki `oku` işlevi tek bir değeri, sahiplik istemeden alıyordu. Aynı
düzenek bir dilim için de geçerli: bir işlev parametresini `&[Iz]` olarak yazarsa, hem
kaynağın tamamını hem de yalnız bir aralığını, sahiplik istemeden kabul edebiliyor.

```rust
// dilim_parametre.rs — bir islev dilim alarak kaynagi tasimadan isler
mod iz;
use iz::{Iz, okunan, yeni_defter};

fn adlari_birlestir(dilim: &[Iz]) -> String {
    let mut sonuc = String::new();
    for (i, iz) in dilim.iter().enumerate() {
        if i > 0 {
            sonuc.push('+');
        }
        sonuc.push_str(&iz.ad);
    }
    sonuc
}

fn main() {
    let defter = yeni_defter();
    let liste = vec![
        Iz::yeni("a", &defter),
        Iz::yeni("b", &defter),
        Iz::yeni("c", &defter),
    ];

    println!("tum liste: {}", adlari_birlestir(&liste));
    println!("ilk iki: {}", adlari_birlestir(&liste[..2]));
    println!("cagrilardan sonra defter: [{}]", okunan(&defter).join(", "));
}
```

```
tum liste: a+b+c
ilk iki: a+b
cagrilardan sonra defter: []
```

`adlari_birlestir` işlevi hem `&liste` (tüm kaynak) hem `&liste[..2]` (bir alt aralık) ile
çağrılabiliyor — parametre tipi `&[Iz]` olduğu için ikisi de aynı işleve uyuyor. `&liste`
burada bir dilime **dönüştürülüyor**: büyüyen dizinin tamamına bir referans, otomatik
olarak baştan sona bir dilime karşılık geliyor. İki çağrıdan sonra da defter boş —
`adlari_birlestir` hiçbir zaman `liste`nin elemanlarına sahip olmadı, yalnız onları okudu.
Bu, bir işlevin sahiplik istemeden **hem bütünü hem parçayı** aynı imzayla kabul
edebilmesinin somut örneği.

#### Değiştirilebilir Dilim, Kapsadığı Elemanları Değiştirir

Buraya kadar görülen dilimler hep paylaşımlıydı (`&[Iz]`). Bir dilim de `&mut [Iz]`
olarak alınabilir ve bu durumda kapsadığı elemanlar üzerinde yazma izni de taşır —
Ödünç Alma dersindeki paylaşımlı/değiştirilebilir ayrımı burada da aynen geçerli.

```rust
// dilim_degistirilebilir.rs — degistirilebilir bir dilim, kapsadigi elemanlari degistirebilir
mod iz;
use iz::{Iz, yeni_defter, okunan};

fn main() {
    let defter = yeni_defter();
    let mut liste = vec![
        Iz::yeni("x", &defter),
        Iz::yeni("y", &defter),
        Iz::yeni("z", &defter),
    ];

    {
        let goruntu = &mut liste[0..2];
        for iz in goruntu.iter_mut() {
            iz.ad.push_str("-yeni");
        }
    }
    println!("degisiklikten sonra adlar: {}, {}, {}", liste[0].ad, liste[1].ad, liste[2].ad);
    println!("hicbir sey bitmedi, defter: [{}]", okunan(&defter).join(", "));
}
```

```
degisiklikten sonra adlar: x-yeni, y-yeni, z
hicbir sey bitmedi, defter: []
```

`goruntu` burada `liste`nin ilk iki elemanını değiştirilebilir olarak görüntülüyor;
döngü içindeki `iz.ad.push_str(...)` bu iki elemanın `ad` alanını gerçekten değiştiriyor.
Üçüncü eleman (`z`) dilimin dışında kaldığı için değişmiyor — çıktı bunu doğruluyor.
Kapsam kapandığında hiçbir değer bitmiyor, çünkü değiştirilebilir bir dilim de, tıpkı
paylaşımlı bir dilim gibi, sahiplik almıyor; yalnız o aralığa yazma izni taşıyor.

Bu örnekte de aynı anda yalnız bir değiştirilebilir dilim var; `goruntu` kapsamdayken
`liste`ye başka hiçbir erişim (ne paylaşımlı ne değiştirilebilir) açılamazdı. `goruntu`nun
kapsamı kapandıktan sonra `liste[0].ad` gibi doğrudan indekslemeler serbestçe kullanılabiliyor
— tıpkı Sınırlayıcı Ölçüm bölümünde görülen `push` örneğinde olduğu gibi, kısıt yalnız
dilimin kendi kapsamı boyunca geçerli.

#### Uzunluk Kaynaktan Türer, Boş Dilim Geçerlidir

Dilimin uzunluğu kendi başına bir bilgi taşımıyor, kaynaktan hesaplanıyor. Bir dizgi
üzerinde de aynı aralık söz dizimi geçerli.

```rust
// dizgi_dilimi.rs — dilimin uzunlugu kaynaktan turer, bos dilim de gecerlidir
fn main() {
    let metin = String::from("olcum");
    let tam = &metin[..];
    let bos = &metin[0..0];
    println!("kaynak uzunluk: {}", metin.len());
    println!("tam dilim uzunluk: {}", tam.len());
    println!("bos dilim uzunluk: {}", bos.len());
    println!("bos dilim gecerli mi: {}", bos.is_empty());
}
```

```
kaynak uzunluk: 5
tam dilim uzunluk: 5
bos dilim uzunluk: 0
bos dilim gecerli mi: true
```

`&metin[..]` bütün aralığı, `&metin[0..0]` ise hiçbir karakter kapsamayan boş bir aralığı
görüntülüyor. `tam.len()` kaynağınkiyle aynı çıkıyor çünkü aralık baştan sona; `bos.len()`
sıfır, ama `bos` geçersiz bir değer değil — kendi başına geçerli bir dilim, yalnız hiçbir
şey kapsamıyor. `is_empty()` çağrısı bunu doğruluyor: boş bir dilim üzerinde çağrılan
sıradan bir yöntem, hiçbir özel durumla karşılaşmadan çalışıyor.

`metin.len()`in burada verdiği sayı dizginin bayt uzunluğu — bu, dizginin kendisinin bir
bayt dizisi olduğu ve karakter sayısından ayrıştığı Koleksiyonlar dersinde (M10/K01) zaten
ele alınmıştı. Bu dersin payı ayrı: aralığın kendisi nasıl kuruluyor ve ne zaman geçerli
sayılıyor. `metin`in içeriği yalnız ASCII karakterler taşıdığı için burada bayt uzunluğu
ile karakter sayısı çakışıyor; aradaki farkın kendisi bu dersin konusu değil.

**SK12.** Bir dilimin `başlangıç == bitiş` olması bir hata durumu değil, sıfır uzunluklu
geçerli bir dilim üretiyor. Bu, bir işlevin örneğin "eşleşen kısım" olarak boş bir aralık
döndürebilmesini, çağıranın bunu ayrı bir özel durum olarak ele almak zorunda kalmadan
işleyebilmesini sağlıyor. Boş bir dilim üzerinde `len()`, `is_empty()`, hatta bir döngüyle
gezinme (sıfır kez dönerek) sorunsuz çalışıyor — kaynağın kendisi boş olmasa bile.

Dört ders boyunca ödünç almanın taşıdığı üç soru burada da aynı yanıtları veriyor: kaynak
bitiyor mu (hayır), ömür uzuyor mu (hayır, dilimin kapsamı kaynağınkini hiçbir zaman
aşamıyor) ve paylaşımlı/değiştirilebilir ayrımı geçerli mi (evet — bir `&mut [Iz]` dilimi
de alınabilirdi, o zaman kısıtlar Ödünç Alma dersindeki değiştirilebilir referansla
birebir aynı olurdu). Dilim, bu üç soruya yeni bir yanıt getirmiyor; sahip olduğu tek yeni
şey, görüntülediği aralığın **boyutu** — tek bir değer yerine ardışık bir küme.

#### Özet

- Bir dilim (`&[T]`, `&str`), kaynağın ardışık bir aralığını sahiplik almadan görüntüler;
  kaynağın kendisi dilim yüzünden hiçbir zaman bitmiyor — kaynağın ömrü kendi **kapsam
  sonunda** bitiyor.
- Dilim yalnız işaret ettiği aralığı değil, kaynağın **bütününü** kilitliyor — dilim
  yaşarken kaynak değiştirilemiyor, dilim bittikten sonra değişiklik sorunsuz geçiyor.
- Dilimin uzunluğu kaynaktan türüyor; bir dilim kendi başına bağımsız bir uzunluk bilgisi
  taşımıyor.
- `başlangıç == bitiş` olan bir dilim geçerlidir ve sıfır uzunluk taşır; boş bir dilim özel
  bir durum değildir.
- Dilim de bir referans olduğu için önceki iki dersin bütün kuralları (paylaşımlı/
  değiştirilebilir ayrımı, kapsamın kaynağı aşamaması) burada da geçerli.
- Bir işlev parametresini `&[T]` ya da `&mut [T]` yazmak, o işlevin hem kaynağın
  tamamını hem yalnız bir aralığını, sahiplik almadan aynı imzayla kabul etmesini sağlar.

#### Sonraki Adım

Bu dört ders boyunca ödünç almanın kuralları tek tek ölçüldü — bütün değer, bir parça,
paylaşımlı ya da değiştirilebilir; her seferinde kaynak bitmedi, ömür kaynağı aşmadı ve
aynı anda bir yazan ya da çok okuyan kısıtı korundu. Bu kurallar dört ayrı ders boyunca hiç
çelişmeden aynı kaldı, yalnız uygulandıkları yüzey değişti. Sıradaki ders bu kuralları
uygulayan mekanizmanın kendisine dönüyor: ödünç denetleyicisi, derleme zamanında tam olarak
neyi sınıyor ve bu denetim aynı işi yapan farklı yazımlar arasında nasıl bir seçim
bırakıyor?

### Ödünç Denetleyicisi

Source: https://academia.sh/tr/kurslar/sahiplik/odunc-denetleyicisi

Ödünç denetleyicisi, derleme zamanında bir değerin sahiplik ve ödünç kurallarını sınar; üç redd örneği (taşıma sırasında canlı bir ödünç, okurken değiştirme, yerel bir sahibe referans döndürme) hep düzyazıda tarif edilir, yanlarına kabul edilen çözüm koşturulur. Aynı işi yapan iki farklı çözüm aynı defter kaydını üretebilir; ödünç kurallarına uyan bir kod ise yine de yanlış bir sonuç verebilir — denetleyici doğruluğu değil, yalnız sahiplik disiplinini güvence altına alır.

Önceki dört ders ödünç almanın kurallarını tek tek kurdu: sahiplik vermeden erişim, kaynağın
bitmemesi, ömrün kaynağı aşmaması, paylaşımlı/değiştirilebilir ayrımı. Bu ders bu kuralları
uygulayan mekanizmanın kendisine bakıyor: ödünç denetleyicisi derleme zamanında tam olarak neyi
sınıyor? Denetleyicinin izlediği şey bir değerin ömrüdür — Eşzamanlılık kursunda (M09/K03)
sorulan "koşan bir birim nasıl duracak" sorusu değil.

Dört dersin de ortak bir varsayımı vardı: gösterilen her kod zaten kurala uyuyordu, kabul
edilen tarafta duruyordu. Bu ders o çizginin kendisini görünür kılıyor — kuralın neyi
ayırdığını, hem reddedilen tarafı düzyazıyla tarif ederek hem kabul edilen tarafı
koşturarak gösteriyor. Aynı işi yapan birden çok kabul edilen yazımın var olabilmesi de bu
dersin ayrı bir bulgusu: kural tek bir doğru biçim dayatmıyor, yalnız bir sınır çiziyor.

Derleyicinin bir yazımı reddetmesi bu müfredatta ilk kez Go'nun Tasarım Amaçları dersinde
(M09/K01) ana ölçü ekseniydi — orada kaynağın derlenip derlenmediğinin kendisi ölçülüyordu.
Bu kursta aynı soru kursun ana ölçümü **olamaz**; yalnız bu dersin sınırlı payı. Kalan dört
dersin hiçbirinde olmadığı kadar çok redd bu derste görülüyor, ama her biri aynı kurala
bağlı kalıyor: **redd düzyazıda tarif edilir, kabul edilen çözüm koşturulur.**

Önceki üç dersteki reddler tek tek, birer kuralın somut örneğiydi — bu derste üç redd
yan yana durup denetleyicinin genel çalışma biçimini gösteriyor. Üçünün de ortak yanı şu:
denetleyici bir kaynağı satır satır okumuyor, kaynaktaki her değerin ne kadar süre
geçerli olduğunu ve o süre boyunca kimin hangi yetkiyle eriştiğini bir bütün olarak
izliyor. Bir satırın kendi başına geçerli görünmesi yetmiyor; o satırın önceki ve sonraki
satırlarla birlikte kurduğu ilişki de kurala uymak zorunda.

#### Redd 1: Taşıma Sırasında Canlı Bir Ödünç

Bir değer ödünç verilmişken taşınamaz. `deger`e bir referans (`bakis`) alınmışken aynı
`deger`i bir işleve taşımaya çalışan bir çağrı derlenmez — çünkü taşıma eski adı geçersiz
kılıyor, ama `bakis` hâlâ o adın işaret ettiği yere bakıyor olurdu. Bu ihlali gösteren bir
kaynak hiç yazılmıyor; onun yerine aynı işi yapan iki ayrı **kabul edilen** çözüm
koşturuluyor ve ikisinin de aynı defter kaydını ürettiği ölçülüyor.

Bu redd, Sahiplik ve Taşıma dersindeki tek-sahip kuralı ile Ödünç Alma dersindeki
kapsam-içi-kalma kuralının kesiştiği yer. Taşıma tek başına serbest, ödünç alma tek
başına serbest; ikisi aynı değer üzerinde, aynı anda çakıştığında denetleyici devreye
giriyor. Taşıma eski adı geçersiz kılarken elde kalan bir referansın ne olacağı
belirsizleşiyor — denetleyici bu belirsizliği, taşımaya izin vermeden önce üzerindeki
bütün ödünçlerin kapanmış olmasını isteyerek gideriyor.

**Çözüm A — kapsam daraltma:** referans kendi dar kapsamında bırakılıp taşımadan önce
kapatılıyor.

```rust
// iz.rs — bir degerin bitisini kaydeden olcum yardimcisi
use std::cell::RefCell;
use std::rc::Rc;

pub type Defter = Rc<RefCell<Vec<String>>>;

pub struct Iz {
    pub ad: String,
    defter: Defter,
}

impl Iz {
    pub fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz { ad: ad.to_string(), defter: Rc::clone(defter) }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

pub fn yeni_defter() -> Defter {
    Rc::new(RefCell::new(Vec::new()))
}

pub fn okunan(defter: &Defter) -> Vec<String> {
    defter.borrow().clone()
}
```

```rust
// kapsam_daraltma.rs — odunc, tasimadan once dar bir kapsamda bitiriliyor
mod iz;
use iz::{Iz, yeni_defter, okunan};

fn gorevi_isle(deger: Iz) {
    println!("islev icinde tasinan ad: {}", deger.ad);
}

fn main() {
    let defter = yeni_defter();
    let deger = Iz::yeni("gorev", &defter);

    {
        let bakis = &deger;
        println!("mevcut ad: {}", bakis.ad);
    }
    gorevi_isle(deger);
    println!("kapsam daraltma sonrasi defter: [{}]", okunan(&defter).join(", "));
}
```

```
mevcut ad: gorev
islev icinde tasinan ad: gorev
kapsam daraltma sonrasi defter: [gorev]
```

**Çözüm B — kopya alma:** okuma için gereken veri baştan kopyalanıyor, `deger`e hiç
referans alınmıyor.

```rust
// kopya_alma.rs — okunacak veri onceden kopyalanip odunc hic alinmiyor
mod iz;
use iz::{Iz, yeni_defter, okunan};

fn gorevi_isle(deger: Iz) {
    println!("islev icinde tasinan ad: {}", deger.ad);
}

fn main() {
    let defter = yeni_defter();
    let deger = Iz::yeni("gorev", &defter);

    let mevcut_ad = deger.ad.clone();
    println!("mevcut ad: {}", mevcut_ad);
    gorevi_isle(deger);
    println!("kopya alma sonrasi defter: [{}]", okunan(&defter).join(", "));
}
```

```
mevcut ad: gorev
islev icinde tasinan ad: gorev
kopya alma sonrasi defter: [gorev]
```

**SK13.** İki çözüm de aynı defter kaydını (`[gorev]`) üretiyor. Denetleyici tek bir doğru
yazım dayatmıyor; yalnız bir kuralı (taşıma sırasında canlı bir ödünç olamaz) uyguluyor ve
bu kuralı sağlayan her yazım kabul ediliyor. Kapsam daraltma referansın ömrünü kısaltıyor,
kopya alma referansı hiç kurmuyor — ikisi de farklı bir yoldan aynı kurala uyuyor ve aynı
gözlemlenebilir sonuca varıyor.

İki çözüm arasındaki fark maliyette. Kapsam daraltma hiçbir yeni veri kurmuyor, yalnız
referansın kapsamını daraltıyor; kopya alma ise `deger.ad`in bir kopyasını çıkarıyor —
`Iz`in kendisi hâlâ tek, ama `ad` alanının içeriği bir kez daha kuruluyor. İki yazım da
aynı kurala uyuyor, ama hangisinin seçileceği kaynağın geri kalanına bağlı: referansın
kapsamı dar bir bloğa sığdırılabiliyorsa kapsam daraltma tercih edilir; okunacak veri
işlevin farklı noktalarında tekrar tekrar gerekiyorsa kopya almak daha sade kalabilir.

#### Redd 2: Okurken Değiştirme

Bir listenin üzerinde paylaşımlı bir ödünçle (örneğin bir döngüyle) gezinirken aynı listeyi
değiştirmeye çalışmak da reddediliyor — döngünün kendisi listeye bir paylaşımlı referans
tutarken, listeye eleman eklemek değiştirilebilir bir referans istiyor ve ikisi çakışıyor.
Çözüm, okuma ile yazmayı iki ayrı adıma bölmek. Bu kalıp, bir koleksiyonun her elemanından
türeyen yeni elemanları aynı koleksiyona eklemek istendiğinde sıkça karşılaşılan bir
durum — koleksiyonun kendi üzerinde gezinirken kendisini büyütmeye çalışmak.

```rust
// okuma_sonra_yazma.rs — once paylasimli odunc ile okunur, sonra ayri bir adimda degistirilir
mod iz;
use iz::{Iz, yeni_defter, okunan};

fn main() {
    let defter = yeni_defter();
    let mut liste = vec![Iz::yeni("p", &defter), Iz::yeni("q", &defter)];

    let mut kopya_adlari = Vec::new();
    for iz in &liste {
        kopya_adlari.push(format!("{}-kopya", iz.ad));
    }

    for ad in &kopya_adlari {
        liste.push(Iz::yeni(ad, &defter));
    }

    println!("liste uzunlugu: {}", liste.len());
    println!("henuz biten yok, defter: [{}]", okunan(&defter).join(", "));
}
```

```
liste uzunlugu: 4
henuz biten yok, defter: []
```

İlk döngü `&liste` üzerinde gezinip her adın bir kopyasını ayrı bir `Vec<String>`e
topluyor; bu döngü bittiğinde paylaşımlı ödünç de kapanıyor. İkinci döngü `liste`yi
serbestçe değiştiriyor, çünkü artık üzerinde hiçbir ödünç yok. Aynı işi tek bir döngüde,
gezinme sürerken listeye eleman ekleyerek yapmaya çalışan bir yazım derlenmezdi.

Bu redd Redd 1'le aynı aileden, ama kaynağı farklı. Redd 1'de çakışan iki şey bir taşıma
ile bir ödünçtü; burada çakışan iki şey bir paylaşımlı ödünç (döngünün kendisi) ile bir
değiştirilebilir ödünç (`push` çağrısı). İkisinin ortak noktası, denetleyicinin çakışmayı
satırların **sırasına** değil, ödünçlerin **kapsamlarının örtüşüp örtüşmediğine** bakarak
bulması. Döngü `liste`nin her elemanını teker teker ziyaret ederken bile, döngünün kendisi
`liste` üzerinde tek, sürekli bir paylaşımlı ödünç tutuyor — döngü bitene kadar kapanmıyor.

#### Redd 3: Yerel Bir Sahibe Referans Döndürmek

Bir işlev kendi içinde kurduğu bir değere referans döndüremez — işlev bitince o değerin
sahibi (işlevin kendi kapsamı) da bitiyor, döndürülen referans artık var olmayan bir yere
işaret ederdi. Çözüm, Sahiplik ve Taşıma dersinde kurulan düzenin aynısı: referans değil,
değerin **kendisini** döndürmek.

İlk iki redd, ödünç ile taşımanın ya da ödünç ile başka bir ödüncün aynı kapsamda
çakışmasıydı — her ikisinde de sorunlu iki erişim aynı satırlar arasında, aynı kaynak
içinde duruyordu. Üçüncü redd farklı: sorun tek bir işlevin sınırını aşıyor, çağıran
tarafla çağrılan taraf arasında.

```rust
// sahiplik_dondur.rs — islev yerel degeri referans degil, sahiplikle donduruyor
mod iz;
use iz::{Iz, yeni_defter, okunan, Defter};

fn olustur(ad: &str, defter: &Defter) -> Iz {
    let yerel = Iz::yeni(ad, defter);
    yerel
}

fn main() {
    let defter = yeni_defter();
    let deger = olustur("uretilen", &defter);
    println!("uretilen ad: {}", deger.ad);
    println!("deger hala sahibinde, defter: [{}]", okunan(&defter).join(", "));
}
```

```
uretilen ad: uretilen
deger hala sahibinde, defter: []
```

`olustur` işlevi `yerel`i kendi gövdesinde kuruyor ve onu **taşıyarak** döndürüyor —
`&yerel` değil, `yerel`in kendisi. Sahiplik çağırana geçtiği için `deger` `main`in sonuna
kadar geçerli kalıyor; defter hâlâ boş. `olustur`un imzası `&Iz` döndürseydi, derleyici bu
imzayı bile kabul etmezdi, çünkü döndürülecek referansın hangi kaynağa bağlı olduğu
belirsiz kalırdı — işlev içinde kurulan `yerel`in kendisi işlev bitince bitiyor.

Bu redd önceki ikisinden farklı bir yerde duruyor: Redd 1 ve Redd 2 belirli bir çağrı
sırasını yasaklıyordu, kaynağın kendisi baştan itibaren geçersizdi. Burada asıl reddedilen
şey, işlevin **imzası** — `fn olustur(...) -> &Iz` yazımı, gövdesine hiç bakılmadan
sorunlu. Bir işlevin döndürdüğü bir referansın nereye bağlı olduğu, işlevin çağrıldığı her
yerde bilinmesi gereken bir bilgi; işlev kendi içinde kurduğu bir değere referans
döndürdüğünde bu bilgi kaynakta hiçbir yerde yazılı değil. Sahiplik ve Taşıma dersinde
görülen "işlevin sahip olduğu bir değeri geri döndürmesi bir taşımadır" kuralı burada tek
çözüm olarak geri dönüyor.

**SK14.** Bu redd, bir referansın geçerli olduğu aralığın kaynağının kapsamını hiçbir
zaman aşamaması kuralının (Ödünç Alma dersi) doğrudan bir sonucu. Burada henüz adı
konmamış bir kavram devreye giriyor: bir referansın "ne kadar süre" geçerli kalabileceğini
belirleyen bu aralığın kendi bir adı var, ama bu ders o adı vermiyor.

Bu redd, ilk iki reddin aksine, işlevin çağrıldığı hiçbir yerdeki koda bakmadan, yalnız
`olustur`un kendi gövdesi okunarak tespit edilebiliyor. Denetleyici bunu, işlevin imzasına
bakıp döndürülen referansın hangi parametreye ya da hangi yerel değere bağlı olduğunu
izleyerek yapıyor; `yerel`in kaynağı işlevin dışından gelmediği için, döndürülecek bir
referansın dışarıda geçerli kalabileceği hiçbir yol yok.

#### Sınırlayıcı Ölçüm: Denetleyici Doğruluğu Güvence Altına Almaz

Buraya kadarki bütün örnekler denetleyicinin **neyi** reddettiğini gösterdi. Şimdi tersi:
denetleyicinin kabul ettiği, hiçbir kuralı ihlal etmeyen bir kod, yine de yanlış bir sonuç
verebilir.

```rust
// dogruluk_garantisi_yok.rs — odunc kurallarina uyan kod yine de yanlis sonuc verebilir
fn ekle_ve_say(liste: &mut Vec<i32>, deger: i32) -> usize {
    let uzunluk = liste.len();
    liste.push(deger);
    uzunluk
}

fn main() {
    let mut liste = Vec::new();
    let sayim1 = ekle_ve_say(&mut liste, 10);
    let sayim2 = ekle_ve_say(&mut liste, 20);
    println!("islevin dondurdugu sayimlar: {}, {}", sayim1, sayim2);
    println!("listenin gercek uzunlugu: {}", liste.len());
}
```

```
islevin dondurdugu sayimlar: 0, 1
listenin gercek uzunlugu: 2
```

`ekle_ve_say` hiçbir sahiplik ya da ödünç kuralını ihlal etmiyor — `liste`yi bir
değiştirilebilir referansla alıyor, elemanı ekliyor, geçerli bir sayı döndürüyor. Ama
`uzunluk` eklemeden **önceki** uzunluğu tutuyor, döndürülen değer ise "eklemeden sonraki
sayım" olarak okunmak isteniyorsa yanlış: iki çağrı `0` ve `1` döndürüyor, oysa listenin
gerçek uzunluğu sırasıyla `1` ve `2` olmalıydı.

**SK15.** Ödünç denetleyicisi yalnız **sahiplik ve erişim disiplinini** sınıyor — bir
değere aynı anda kimin, ne yetkiyle eriştiğini. Bir hesabın hangi noktada okunduğu,
bir değişkenin doğru satırda güncellenip güncellenmediği bu denetimin dışında; kaynak
tamamen geçerli bir sahiplik/ödünç düzeni taşırken de mantık hatası barındırabilir. Bu
dersin ölçtüğü tek şey şu: bir kodun derlenmesi, onun **doğru** olduğu anlamına gelmiyor.

Hatanın düzeltilmesi de aynı gözlemi tamamlıyor: sorun sahiplikte değil, `uzunluk`un hangi
satırda okunduğunda.

```rust
// duzeltilmis.rs — ayni islev, uzunluk eklemeden sonra okunuyor
fn ekle_ve_say(liste: &mut Vec<i32>, deger: i32) -> usize {
    liste.push(deger);
    liste.len()
}

fn main() {
    let mut liste = Vec::new();
    let sayim1 = ekle_ve_say(&mut liste, 10);
    let sayim2 = ekle_ve_say(&mut liste, 20);
    println!("islevin dondurdugu sayimlar: {}, {}", sayim1, sayim2);
    println!("listenin gercek uzunlugu: {}", liste.len());
}
```

```
islevin dondurdugu sayimlar: 1, 2
listenin gercek uzunlugu: 2
```

`liste.push(deger)` ile `liste.len()`in yeri değiştirildi, başka hiçbir şey değişmedi —
parametre tipi, ödünç, imza aynı kaldı. Düzeltilmiş sürüm de tıpkı hatalı sürüm gibi
ödünç denetleyicisinden geçiyor, çünkü denetleyici ikisi arasındaki farkı zaten hiç
görmüyor: her iki sürümde de `liste`ye bir kez değiştirilebilir referans alınıyor, bir kez
kullanılıyor, kural ihlal edilmiyor. Denetleyicinin sessiz kalması, kodun doğru olduğunun
kanıtı değil, yalnız erişim kurallarının ihlal edilmediğinin kanıtı.

Üç redd ve bir doğruluk sınırı, birlikte ödünç denetleyicisinin sınırlarını çiziyor.
Denetleyici bir kaynağı reddettiğinde, sebep her zaman aynı ailede: bir değere aynı anda
birden fazla, birbiriyle çelişen erişimin var olması (Redd 1, Redd 2) ya da bir referansın
kaynağından daha uzun yaşayacak olması (Redd 3). Kabul ettiğinde ise denetleyicinin
söylediği şey dardır — yalnız bu erişim düzeninin güvenli olduğu, kodun yaptığı hesabın
doğru olduğu değil. Dört ders boyunca kurulan sahiplik, taşıma, ödünç ve dilim kuralları
bu dersle birlikte tek bir mekanizmaya, tek bir denetime bağlanıyor; ama o mekanizmanın
sınadığı şeyin sınırları da aynı netlikte görülüyor.

#### Özet

- Ödünç denetleyicisi, derleme zamanında sahiplik ve ödünç kurallarının ihlal edilip
  edilmediğini sınıyor; ihlal eden kaynak hiç derlenmiyor.
- Taşıma sırasında canlı bir ödünç olamaz; kapsam daraltma ve kopya alma bu kısıtı iki
  farklı yoldan sağlayabiliyor ve ikisi de aynı defter kaydını üretiyor: değer iki yazımda
  da **kapsam sonunda** bitiyor.
- Bir kaynak üzerinde paylaşımlı bir ödünçle gezinirken aynı kaynağı değiştirmek
  reddediliyor; okuma ve yazma ayrı adımlara bölünerek çözülüyor.
- Bir işlev kendi içinde kurduğu bir değere referans döndüremez; çözüm, referans değil
  değerin kendisini (sahiplikle) döndürmek.
- Ödünç kurallarına tam uyan bir kod yine de yanlış bir sonuç verebilir — denetleyici
  doğruluğu değil, yalnız erişim disiplinini güvence altına alıyor.
- Aynı kurala uyan birden çok yazım (kapsam daraltma, kopya alma) kabul edilebilir;
  denetleyici tek bir doğru biçim dayatmıyor, yalnız bir sınır çiziyor.

#### Sonraki Adım

Bu derste denetleyicinin sınadığı şeyin bir **aralık** olduğu defalarca görüldü — bir
referansın ne kadar süre geçerli kalabileceğini belirleyen bir sınır. Redd 1'de bu aralık
bir taşımayla çakışmamak zorundaydı, Redd 2'de bir değişiklikle çakışmamak zorundaydı,
Redd 3'te ise kaynağının kendi kapsamını hiçbir zaman aşamıyordu. Üçü de aynı şeyden söz
ediyor, ama bu aralığın kendi adı bu beş ders boyunca hiç konmadı. Sıradaki bölüm tam
olarak bu adı koyuyor: bir referansın geçerlilik aralığının kendi kavramı, bu aralığın ne
zaman kaynaktan okunabildiği ve ne zaman açıkça yazılması gerektiği.

## Yaşam Süreleri

Bir referansın geçerlilik aralığının bir kavram olarak kurulması, iki kaynağın ömrü ayrıştığında açıklamanın yazılmasının zorunlu olması, derleyicinin yazılmayan açıklamayı hangi kurallarla türettiği, ve bir yapının alanında referans tutmanın yapının kendi ömrüne getirdiği koşul.

### Yaşam Süresi Kavramı

Source: https://academia.sh/tr/kurslar/sahiplik/yasam-suresi-kavrami

Bir referansın geçerli olduğu kaynak aralığının bir çalışma zamanı nesnesi olmadığı, yalnız derleyicinin sınadığı bir aralık olduğu kuruluyor. Ödünç Denetleyicisi dersinde sınandığı gösterilen aralığa burada bir ad veriliyor ve iki bağımsız referansın aralığının iç içe olmak zorunda olmadığı ölçülüyor.

Ödünç Denetleyicisi dersi bir şeyi sınadığını gösterdi ama o şeyin adını hiç koymadı:
denetleyici, bir referansın ne kadar süre kullanılabileceğine dair bir aralığı kontrol
ediyordu. Bu ders tam olarak o aralığa bir ad veriyor ve kursun sorusunu ("bu değerin ömrü
nerede bitiyor") bir referansa uyguluyor: bir referansın **kendi** geçerlilik aralığı nereden
nereye uzanıyor ve bu aralık nereden okunuyor.

Eşzamanlılık kursunun (M09/K03) sorduğu soru farklıydı — orada koşan bir birimin ne zaman
duracağı ölçülüyordu, dışarıdan bir kararla (kanal kapanması, bağlam iptali) tetiklenen bir
durma. Burada ölçülen bir çalışma birimi değil; bir referansın kaynakta hangi aralıkta
kullanılabildiği. Ödünç Alma dersi bu aralığın **sonucunu** zaten göstermişti: bir referans
kapsamı biterken kendisi bir şey bitirmiyordu, ödünç verdiği değer hâlâ yaşıyordu. Bu ders o
sonucun **nedenine** iniyor — referansın kendisine ait, adı konmuş bir aralık var mı, varsa bu
aralık nasıl belirleniyor.

#### Bir Aralığın Adı

Rust'ta **yaşam süresi (lifetime)**, bir referansın geçerli kabul edildiği kaynak aralığının
adıdır. Bu aralığın iki ucu var: referansın oluşturulduğu nokta ve son kullanıldığı nokta.
Yaşam süresi bu iki nokta arasındaki mesafeyi tanımlıyor ve derleyici, bir referansın bu
aralığın dışında kullanılmadığından emin oluyor. Bu denetim olmadığında bir referans, verdiği
değer bittikten sonra da elde tutulabilir ve üzerinden okuma yapılmaya çalışılabilirdi; sonuç,
artık geçerli olmayan bir belleğe bakan, tanımsız bir okuma olurdu. Rust bu durumu çalışma
zamanına hiç bırakmıyor: aralık ihlali, program bir kez bile koşmadan, derleme sırasında
yakalanıyor.

Burada kurulması gereken tek ve en önemli ayrım şu: yaşam süresi bir **çalışma zamanı**
nesnesi değildir. Programın koşumu sırasında hiçbir yerde "bu referansın yaşam süresi" diye
saklanan bir sayaç, bir zaman damgası ya da bir kayıt yok. Önceki derste ölçülen `Iz` tipi
`Drop` trait'ini uyguluyordu ve bir değer bittiğinde bunu deftere yazıyordu — ama bu, **sahip
olunan değerin** bitişiydi. Bir referans (`&Iz`) `Drop` uygulamıyor; referansın kendisi hiçbir
zaman deftere düşmüyor, çünkü onun "bitişi" çalışma zamanında gerçekleşen bir olay değil,
derleme zamanında doğrulanan bir sınırdır. Yaşam süresi, kaynaktaki blok yapısından
**okunuyor**; koşum bittiğinde geriye ona ait hiçbir iz kalmıyor.

**YS1.** Yaşam süresi bir değer değil, derleyicinin kaynak üzerinde yürüttüğü bir çıkarımın
adıdır — programın kendisi çalışırken hiçbir yerde saklanmıyor. Bu, kursun önceki
derslerinde ölçülen dört bitiş sınıfından hiçbirine girmiyor: yaşam süresi bir değerin
bitişi değil, bir referansın **geçerli sayıldığı** aralık; ölçülen şey bir olay değil, bir
kaynak aralığı.

Bu sınır, bir kez kurulduktan sonra kursun geri kalanında tekrar tekrar kullanılacak: her
yeni düzenek (açık açıklama, çıkarım kuralı, yapı alanı, öbekte tekil sahiplik, paylaşımlı
sahiplik) aynı soruya farklı bir açıdan yaklaşacak, ama hepsi aynı temele — bir referansın
sahibinden uzun yaşayamayacağı gerçeğine — dayanacak.

Rust'ın kendisi, gerektiğinde bir yaşam süresini kesikli çizgiyle başlayan kısa bir adla
(`'a`, `'b`) yazıya döker; bu adlandırma bir değer değil, yalnızca derleyiciye ve okuyan kişiye
"şu referansla şu referans aynı aralığa bağlı" demenin bir yolu. Bu adların ne zaman
yazılmasının gerektiği ve neyi ifade ettiği sıradaki dersin konusu; burada önemli olan
yalnızca şu: bir aralığın adı olması, o aralığı çalışma zamanında var eden bir şey değil.

#### Kapsam ile Yaşam Süresi Arasındaki Fark

Programlama Temelleri kursu (M01/K02) kapsam (scope) kavramını kurmuştu: bir adın hangi
blokta göründüğü ve o bloktan çıkınca erişilemez hâle geldiği. Yaşam süresi bu kavramla
ilişkili ama aynı şey değil. Kapsam sözdizimsel bir sınırdır — kaynaktaki `{` ve `}`
çiftleriyle çizilir ve bir bloğun tamamını kapsar. Yaşam süresi ise bir **kullanım**
aralığıdır: bir referansın gerçekten geçerli olması gereken aralık, içinde bulunduğu bloğun
tamamı değil, yalnızca oluşturulduğu noktadan son kullanıldığı noktaya kadar olan kesimdir.

Aşağıdaki ölçümde bu ayrım somutlaşıyor: `r1`, `r2`, `r3` referansları bir kapsamın içinde
oluşturuluyor ama o kapsamın **tamamını** doldurmuyor — son kullanıldıkları satırdan sonra
kapsam kapanana kadar hâlâ birkaç satır kod çalışıyor ve bu satırlar artık referanslara hiç
dokunmuyor. Referansların geçerlilik aralığı oluşturuldukları yerden son kullanıldıkları yere
kadar uzanıyor; kapsamın geri kalanı, üç değerin **sahipliği** açısından hâlâ önemli (üçü de
kapsam kapanana kadar canlı), ama referanslar açısından artık konu dışı. Bu, yaşam süresinin
neden ayrı bir kavram olarak adlandırıldığını gösteriyor: kapsam tek başına, bir referansın ne
zamana kadar güvenli olduğunu söylemeye yetmiyor.

Bu fark tek yönlü değil: bir referansın aralığı, kapsamın **tamamını doldurmak zorunda
olmasa** da, kapsamın **dışına da taşamaz**. Bir referans, ait olduğu bloktan çıktıktan sonra
hiçbir biçimde kullanılmaya devam edemez — geçerlilik aralığı kapsamın bir alt kümesidir,
kapsamdan bağımsız, ondan tamamen kopuk bir çizgi değil. Sonraki derslerde görülecek açık
yaşam süresi açıklamaları da bu ilişkiyi bozmuyor; yalnızca birden çok referansın aralığı
arasında bir bağ olduğunda, bu bağı kaynağa yazılı hâle getiriyor.

#### Ölçüm: Bir Referansın Aralığı Sahibin Ömrü İçinde Kalıyor

Yığıt ve Öbek dersindeki ölçüm çekirdeğinin A bölümü üç değerin (`kapsam-1`, `kapsam-2`,
`kapsam-3`) aynı kapsamda kurulup kapsam kapanınca bildirimin tersi sırayla bittiğini
göstermişti. Aynı kesit burada referans alınarak yeniden koşturuluyor: üç değere kapsam
içindeyken birer referans alınıyor, o referanslar üzerinden okuma yapılıyor ve okuma anında
deftere bakılıyor.

```rust
// referans_araligi.rs — omur.rs'in A bolumu kesiti: uc deger, referans uzerinden okunuyor.

use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz { ad: ad.to_string(), defter: Rc::clone(defter) }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

fn okunan(defter: &Defter) -> Vec<String> {
    defter.borrow().clone()
}

fn yeni_olanlar(defter: &Defter, onceki: usize) -> String {
    let hepsi = okunan(defter);
    hepsi[onceki..].join(", ")
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));

    let a0 = okunan(&defter).len();
    {
        let kapsam_1 = Iz::yeni("kapsam-1", &defter);
        let kapsam_2 = Iz::yeni("kapsam-2", &defter);
        let kapsam_3 = Iz::yeni("kapsam-3", &defter);

        let r1 = &kapsam_1;
        let r2 = &kapsam_2;
        let r3 = &kapsam_3;
        println!("referanslar uzerinden okuma -> {}, {}, {}", r1.ad, r2.ad, r3.ad);
        println!("okuma aninda defter        -> [{}]", yeni_olanlar(&defter, a0));

        // Referanslarin son kullanimi yukaridaki satirdaydi; asagida hicbiri gecmiyor ama
        // uc deger de kapsam kapanana kadar sahibi olarak yasamaya devam ediyor.
        let hala_bos = yeni_olanlar(&defter, a0).is_empty();
        println!("kapsam hala acikken defter bos mu -> {}", hala_bos);
    }
    println!("kapsam kapaninca            -> {}", yeni_olanlar(&defter, a0));
}
```

```
referanslar uzerinden okuma -> kapsam-1, kapsam-2, kapsam-3
okuma aninda defter        -> []
kapsam hala acikken defter bos mu -> true
kapsam kapaninca            -> kapsam-3, kapsam-2, kapsam-1
```

`r1`, `r2`, `r3` referansları oluşturulup okunduğu anda defter hâlâ boş — üç değer de henüz
canlı, çünkü kapsam henüz kapanmadı. Referansların son kullanımı da tam bu satırda: bir daha
kullanılmıyorlar. Ardından gelen satır referanslara hiç dokunmadan defterin hâlâ boş olduğunu
doğruluyor — üç değer de, referanslar iş bitirdikten sonra bile, kapsamın kendi sonuna kadar
sahip olarak yaşamaya devam ediyor. Kapsam kapandığında bildirimin tersi sırayla bitiyorlar —
Yığıt ve Öbek dersinde kurulan kural burada da geçerli. Referansların kendi geçerlilik aralığı
bu üç bağlamanın ömrünün **içine** yerleşiyor; dışına taşmıyor, ama bağlamaların ömrünün
tamamını doldurmak zorunda da değil.

**YS2.** Bir referansın geçerlilik aralığı, referans verdiği değerin ömrünün bir alt
aralığıdır — referans, sahibinin bittiği noktadan sonra hiçbir zaman kullanılamaz. Bu sınırı
aşan bir yazım derleyici tarafından reddedilir; reddin somut biçimi Ödünç Denetleyicisi
dersinde koşturularak gösterilmişti.

Yukarıdaki ölçümde `r1` gibi bir referansın iç kapsamın dışına taşınmaya çalışıldığını
düşünelim: `r1`'in dış kapsamda tanımlı bir değişkene atanması ya da bir işlevden döndürülmesi
istensin. Bu yazım derlenmez, çünkü `r1`'in bağlı olduğu `kapsam_1` iç kapsam kapanınca
bitiyor ve `r1` o noktadan sonra da yaşamaya devam eden bir yerde tutulmuş olurdu — bir
referansın kendi sahibinden uzun yaşaması, tam olarak yaşam süresinin izin vermediği durum.
Yukarıdaki koşum kabul edildi çünkü üç referans da yalnızca kendi iç kapsamlarının içinde
kaldı; kabul edilenle reddedilen arasındaki fark, referansın kullanım yerinin sahibin
kapsamının içinde mi dışında mı olduğu.

#### Sınırlayıcı Ölçüm: Aralık İç İçe Olmak Zorunda Değil

Ders kitaplarında yaşam süresi sık sık iç içe geçmiş kutular gibi çizilir ve bu çizim yanlış
bir izlenim bırakabilir: sanki her referansın aralığı bir üst aralığın içine yuvalanmak
zorundaymış gibi. Oysa iki bağımsız referansın aralığının birbiriyle hiçbir ilişkisi olmak
zorunda değil — hatta hiç kesişmeleri bile gerekmiyor.

```rust
// bagimsiz_araliklar.rs — iki referansin gecerlilik araligi hic kesismiyor.

use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz { ad: ad.to_string(), defter: Rc::clone(defter) }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

fn okunan(defter: &Defter) -> Vec<String> {
    defter.borrow().clone()
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));

    let iz_a = Iz::yeni("bagimsiz-a", &defter);
    let iz_b = Iz::yeni("bagimsiz-b", &defter);

    {
        let r = &iz_a;
        println!("a uzerinden okuma -> {}", r.ad);
    }
    println!("a okunduktan sonra defter -> [{}]", okunan(&defter).join(", "));

    {
        let r = &iz_b;
        println!("b uzerinden okuma -> {}", r.ad);
    }
    println!("b okunduktan sonra defter -> [{}]", okunan(&defter).join(", "));
}
```

```
a uzerinden okuma -> bagimsiz-a
a okunduktan sonra defter -> []
b uzerinden okuma -> bagimsiz-b
b okunduktan sonra defter -> []
```

`iz_a` ve `iz_b` aynı dış kapsamda birlikte yaşıyor ve ikisi de yalnız programın en sonunda
bitiyor — defter iki okumadan sonra da boş kalıyor, çünkü henüz hiçbiri bitmedi. Ama
referanslara bakıldığında tablo farklı: `iz_a`'ya alınan referans kendi iç bloğunda
oluşturulup orada kullanılıyor ve o blok kapanınca geçerliliğini yitiriyor; `iz_b`'ye alınan
referans ondan sonra, tamamen ayrı bir blokta oluşturuluyor. İki referansın geçerlilik
aralığı zaman içinde hiç üst üste binmiyor — biri tamamen kapandıktan sonra öbürü açılıyor.
Derleyici bu iki aralığı hiçbir noktada karşılaştırmak zorunda kalmıyor, çünkü aralarında
hiçbir ilişki kurulmadı.

**YS3.** İki referansın geçerlilik aralığı iç içe olmak ya da kesişmek zorunda değildir;
birbirinden tamamen bağımsız, hatta zaman içinde hiç örtüşmeyen aralıklar aynı programda yan
yana bulunabilir. Bir işlev imzası iki referans arasında bir ilişki kurmadığı sürece, o iki
aralık derleyici için de birbirinden bağımsız kalır — bu ilişkinin ne zaman kurulması
gerektiği sıradaki dersin konusu.

Bu bağımsızlığın pratik karşılığı şu: bir programda aynı anda onlarca referans yaşayabilir ve
bunların büyük çoğunluğunun birbiriyle hiçbir ilişkisi yoktur — her biri kendi bağımsız
aralığında, kendi sahibine bağlı olarak var olur. Derleyici yalnızca gerçekten ilişkili olan
aralıkları birbiriyle karşılaştırır: bir referans başka bir referansın verisine dayanıyorsa,
ya da bir işlev iki referans arasında bir bağ kuruyorsa. İlişkisiz iki referans hiçbir zaman
bu karşılaştırmaya girmez, tıpkı yukarıdaki `iz_a` ve `iz_b` örneğinde olduğu gibi. Bu, bir
sonraki derste görülecek açık yazımın neden yalnızca **gerektiğinde** ortaya çıktığını da
açıklıyor: bir ilişki yoksa yazılacak bir şey de yok.

#### Aralığın Kaynaktan Okunması

Yukarıdaki iki ölçümün ortak bir özelliği var: hiçbiri bir yaşam süresini doğrudan basmadı.
Basılan tek şey, sahip olunan değerlerin ne zaman bittiğiydi — referansların kendi aralığı
hiçbir çıktıda görünmedi, çünkü görünecek bir çalışma zamanı karşılığı yok. Bir referansın
aralığını öğrenmenin tek yolu kaynağı okumak: `r1`'in aralığı, `let r1 = &kapsam_1;`
satırından `r1.ad`'ın kullanıldığı yazdırma çağrısına kadar uzanıyor; bunun ne öncesinde ne
sonrasında ayrı bir araç çalıştırmaya gerek var.

Bu, kursun önceki derslerinde (ifade/deyim/öğe sınıflandırması, dört bitiş sınıfı) kurulan
kalıbın devamı: her ölçüm, koşum bittikten sonra elde kalan bir sayı ya da sıralı bir kayıt
değil, kaynağın kendi yapısından çıkarılan bir sonuç üretiyor. Yaşam süresi için bu, çıktıda
hiç görünmeyen ama kaynakta her zaman görünür olan bir bilgi anlamına geliyor.

İkinci ölçümde de aynı okuma yöntemi geçerli: `iz_a` üzerindeki referansın aralığını bulmak
için deftere ya da bir başka çıktıya bakmaya gerek yok — kaynakta `let r = &iz_a;` satırından
`r.ad`'ın kullanıldığı satıra kadar olan iç blok, o aralığın tamamı. `iz_b`'ninki de aynı
biçimde, kendi iç bloğuyla sınırlı. İki referansın aralığı arasında kalan satırlar — birinci
blok kapandıktan sonra, ikinci blok açılmadan önceki satır — her iki aralığa da ait değil ve
bu da yalnızca kaynağı okuyarak anlaşılıyor. Bir çalıştırma aracı ya da ek bir araç bu
sonuca hiçbir katkı yapmıyor; ölçüm çekirdeği burada yalnızca zaten doğru olan bir okumayı
somutlaştırmak için var.

#### Özet

- Yaşam süresi (lifetime), bir referansın geçerli kabul edildiği kaynak aralığının adıdır ve
  bir çalışma zamanı nesnesi değildir — yalnız derleyicinin kaynak üzerinde yürüttüğü bir
  çıkarımdır.
- Bir referans `Drop` uygulamaz ve deftere hiçbir zaman düşmez; yalnız sahip olunan değerler
  düşer; sahip olunan değerin ömrü **kapsam sonunda** bitiyor.
- Bir referansın geçerlilik aralığı, referans verdiği değerin ömrünün bir alt aralığıdır ve
  bu aralık sahibinin bitişinden sonrasına taşamaz.
- İki bağımsız referansın geçerlilik aralığı iç içe olmak ya da kesişmek zorunda değildir.
- Bir referansın aralığı hiçbir çıktıda görünmez; tek kaynağı, referansın oluşturulduğu ve
  son kullanıldığı satırların kaynak koddaki yeridir.

#### Sonraki Adım

Bu derste bir referansın aralığının sahibinin ömrü içinde kaldığı, bu aralığın çalışma
zamanında hiçbir iz bırakmadığı ve iki bağımsız aralığın birbiriyle hiçbir ilişkiye
girmeyebileceği görüldü. Ama bazı işlevler tam olarak böyle bir ilişki kurmak zorunda: birden
çok referans alıp içlerinden birini döndüren bir işlev yazıldığında, dönen referansın hangi
girdiye bağlı olduğu kaynaktan tek başına çıkarılamıyor ve derleyici bu belirsizliği kabul
etmiyor. Sıradaki ders bu durumda aralığın nasıl açıkça yazıldığını, bu yazının kaynağı hangi
bilgiyle zenginleştirdiğini ve yazılan şeyin gerçekte tutmadığında ne olduğunu ölçüyor.

### Açık Yaşam Süresi Açıklamaları

Source: https://academia.sh/tr/kurslar/sahiplik/acik-yasam-suresi-aciklamalari

Bir işlev birden çok referans alıp içlerinden birini döndürdüğünde, dönen referansın hangi girdiye bağlı olduğu kaynaktan tek başına çıkarılamaz ve açık bir yaşam süresi açıklaması gerekir. Açıklamanın bir referansın ömrünü uzatmadığı ya da kısaltmadığı, yalnızca var olan bir ilişkiyi kaynağa yazdığı ve derleyicinin bu yazıyı bir istek olarak doğruladığı ölçülüyor.

Önceki ders iki bağımsız referansın aralığının hiçbir ilişkiye girmeden yan yana
durabileceğini gösterdi — çoğu referans birbirinden habersiz yaşar ve derleyici aralarında
hiçbir bağ kurmaz. Ama bir işlev birden çok referans alıp içlerinden birini döndürdüğünde,
artık bağımsızlık yetmiyor: dönen referansın hangi girdiden geldiği, hangi girdinin ömrüne
bağlı olduğu kaynaktan tek başına çıkarılamıyor. Bu ders tam bu noktada devreye giren açık
yazımı — yaşam süresi açıklamasını — ölçüyor: ne zaman gerekiyor, hangi bilgiyi ekliyor ve
derleyici onu nasıl bir söz olarak ele alıyor.

Eşzamanlılık kursunun (M09/K03) ölçtüğü şey burada da geçerli değil: orada koşan bir birimin
durması dışarıdan bir kararla tetikleniyordu, burada ölçülen bir kaynağın kendi imzasına
yazılmış bir ilişki. Yığıt ve Öbek dersinde kurulan dört bitiş sınıfından hiçbiri de burada
işlemiyor; açıklama bir değerin bitişini değil, iki referans arasındaki bir ilişkiyi yazıya
döküyor.

Bu ilişkinin yazılması ihtiyaridir değil zorunludur: derleyici, belirsiz kalan bir imzayı
hiçbir varsayımda bulunmadan reddediyor. Bir insan okuyucu iki referanslı bir işleve bakıp
"muhtemelen ilk parametre döndürülüyor" diye tahmin edebilir, ama derleyici tahmin yürütmüyor
— ya ilişki açıkça yazılı olacak ya da işlev hiç derlenmeyecek. Bu, kursun daha önce kurduğu
bir ilkeyi tekrarlıyor: derleyicinin güvencesi, olası bir doğru okumaya değil, kaynakta
yazılı olan bilgiye dayanıyor.

#### Ne Zaman Yazılması Gerekiyor

Bir işlev tek bir referans alıp bir referans döndürüyorsa, dönen referansın hangi girdiye
bağlı olduğu açık: alınan tek girdi. Ama iki referans alıp bir referans döndüren bir işlevde
bu bağ belirsizleşiyor — derleyici, dönen referansın ilk girdiye mi, ikinci girdiye mi, yoksa
ikisine birden mi bağlı olduğunu kaynaktaki tipe bakarak tek başına söyleyemez. Tam da bu
belirsizlik anında yaşam süresi açıklaması gerekiyor: işlev imzasına yazılan kısa bir ad
(`'a` gibi), hangi girdinin ömrünün dönen referansa taşındığını söylüyor.

Bu belirsizlik yalnızca girdi sayısıyla ilgili değil, dönen değerin bir referans olmasıyla da
ilgili. Bir işlev iki referans alıp bir sayı ya da yeni kurulmuş bir değer döndürüyorsa hiçbir
açıklamaya gerek yok, çünkü dönen değerin ömrü herhangi bir girdiye bağlı değil — kendi başına
var oluyor. Açıklama yalnızca dönen değer **de bir referans olduğunda** ve o referansın hangi
girdiden geldiği tipten okunamadığında devreye giriyor. Aşağıdaki ölçüm tam bu durumu kuruyor:
iki `Iz` referansı alan, ama yalnızca birinden türeyen bir dize dilimi döndüren bir işlev.

```rust
// iki_kaynakli_donus.rs — donen referans yalnizca 'a'yi tasiyan girdiye bagli.

use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz { ad: ad.to_string(), defter: Rc::clone(defter) }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

fn okunan(defter: &Defter) -> Vec<String> {
    defter.borrow().clone()
}

// 'a yalnizca oncelikli ve donen deger arasinda kuruluyor; digeri bu iliskiye girmiyor.
fn oncelikli_ad<'a>(oncelikli: &'a Iz, digeri: &Iz) -> &'a str {
    println!("digeri de gorunuyor -> {}", digeri.ad);
    &oncelikli.ad
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));

    let disarida = Iz::yeni("disarida-yasayan", &defter);
    let sonuc;
    {
        let iceride = Iz::yeni("iceride-yasayan", &defter);
        sonuc = oncelikli_ad(&disarida, &iceride);
        println!("cagri icinde sonuc -> {}", sonuc);
    }
    println!("ic kapsam bitince defter -> [{}]", okunan(&defter).join(", "));
    println!("sonuc hala kullanilabilir -> {}", sonuc);
}
```

```
digeri de gorunuyor -> iceride-yasayan
cagri icinde sonuc -> disarida-yasayan
ic kapsam bitince defter -> [iceride-yasayan]
sonuc hala kullanilabilir -> disarida-yasayan
```

`oncelikli_ad` iki referans alıyor ama açıklama yalnızca `oncelikli` ile dönen değer arasında
kuruluyor: her ikisi de aynı `'a`'yı taşıyor, `digeri` taşımıyor. Bu, iki kaynağın ömrünün
**ayrıştığı** bir durum — `disarida` dış kapsamda, `iceride` iç kapsamda yaşıyor ve ikisinin
ömrü farklı uzunlukta. Ölçüm bunu doğruluyor: iç kapsam kapanıp `iceride-yasayan` deftere
düştükten sonra bile `sonuc` hâlâ kullanılabiliyor, çünkü `sonuc` yalnızca `disarida`'nın
ömrüne bağlı — `digeri`'nin (yani `iceride`'nin) ömrüne hiç bağlı değil.

**YS4.** Açık yaşam süresi açıklaması, iki referans arasında **var olan** bir ilişkiyi
kaynağa yazıyor; ilişkiyi kurmuyor, kurulu olanı görünür kılıyor. `oncelikli_ad` işlevinde bu
ilişki yalnızca `oncelikli` ile dönen değer arasında; `digeri` işlevin gövdesinde kullanılsa
bile açıklamanın dışında kalıyor.

Ölçümde `digeri` (`iceride`'ye bağlı) kaybolduktan sonra `sonuc`'un hâlâ kullanılabilmesi
tesadüf değil, imzanın doğrudan söylediği bir sonuç. `disarida`, `iceride`'den önce kurulmuş
ve iç kapsam kapanana kadar hâlâ ayakta; `sonuc` da `disarida`'nın ömrüne bağlı olduğu için,
`iceride` bitse bile geçerliliğini koruyor. Eğer işlev `digeri`'yi döndürseydi, aynı çağrı
`iceride`'nin ömrü bitince artık kullanılamayan bir referans üretirdi — bu da imzanın neden
`oncelikli`'yi seçtiğini, `digeri`'yi değil, somutlaştırıyor.

Burada dikkat edilmesi gereken bir nokta daha var: `'a` yazımı, `disarida`'nın ömrünü ne
uzatıyor ne kısaltıyor. `disarida` zaten dış kapsamda, `iceride`'den önce kurulmuş ve dış
kapsamın sonuna kadar yaşayacaktı — açıklama olmasaydı da bu değişmezdi. Açıklamanın tek işi,
dönen referansın **hangi** ömre bağlı olduğunu derleyiciye ve okuyan kişiye söylemek; kendisi
hiçbir ömrü değiştirmiyor.

#### Açıklamanın Kapsadığı ve Kapsamadığı

`oncelikli_ad` imzasında `'a` yalnızca `oncelikli` ve dönen değer arasında geçiyor; `digeri`
parametresi kendi ayrı, adlandırılmamış bir ömre sahip ve bu ömrün `'a` ile hiçbir ilişkisi
yok. Bu, iki referansın **aynı** işlev çağrısında bir arada bulunmasının, aralarında bir ilişki
kurulduğu anlamına gelmediğini gösteriyor — ilişki yalnızca imzada **yazılan** kadar var.
`digeri`'nin ömrü `oncelikli`'ninkinden kısa da olabilir, ondan uzun da; işlev bunu hiç
umursamıyor, çünkü gövde `digeri`'yi yalnızca okumak için kullanıyor, döndürmek için değil.

Bu, açıklamanın imzada olabildiğince az şey söylemesinin bir erdem olduğunu gösteriyor.
`digeri` parametresine bir ad vermek zorunda değildik — kendi ömrü hiçbir yerde
kullanılmayacaksa, derleyici onu kendiliğinden ayrı ve adsız bir aralık olarak ele alıyor.
Yalnızca gerçekten paylaşılan bir ilişki varsa bir ad gerekiyor; ilişki yoksa ad da yok.

Bu ayrım, önceki dersteki sınırlayıcı ölçümle aynı köke dayanıyor: bir işlev imzası iki
referans arasında bir bağ kurmadığı sürece, o iki referansın aralığı derleyici için
bağımsız kalıyor. `'a` burada yalnızca `oncelikli` ile dönen değeri birbirine bağladı;
`digeri`'yi bu bağın dışında bıraktı ve `digeri` kendi bağımsız aralığında kaldı.

Bir imza, tek bir `'a` yerine birden çok adlandırılmış ömür de taşıyabilir — her biri kendi
ilişkisini kurar. Aşağıdaki işlev iki referans alıp ikisini de bir demet içinde döndürüyor;
`'a` yalnızca ilk parçayı, `'b` yalnızca ikinci parçayı bağlıyor ve ikisi arasında hiçbir
ilişki kurulmuyor.

```rust
// iki_isimli_omur.rs — iki ayri isimlendirilmis omur, ikisi de donen demetin ayri bir parcasina bagli.

use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz { ad: ad.to_string(), defter: Rc::clone(defter) }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

fn okunan(defter: &Defter) -> Vec<String> {
    defter.borrow().clone()
}

// 'a ve 'b birbirinden bagimsiz: hicbiri otekini kisitlamiyor.
fn ikisini_de_dondur<'a, 'b>(x: &'a Iz, y: &'b Iz) -> (&'a str, &'b str) {
    (&x.ad, &y.ad)
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));

    let disarida = Iz::yeni("uzun-omurlu", &defter);
    let ilk;
    {
        let iceride = Iz::yeni("kisa-omurlu", &defter);
        let (a, b) = ikisini_de_dondur(&disarida, &iceride);
        ilk = a;
        println!("ic kapsam icinde -> {}, {}", ilk, b);
    }
    println!("ic kapsam bitince defter -> [{}]", okunan(&defter).join(", "));
    println!("ilk hala kullanilabilir -> {}", ilk);
}
```

```
ic kapsam icinde -> uzun-omurlu, kisa-omurlu
ic kapsam bitince defter -> [kisa-omurlu]
ilk hala kullanilabilir -> uzun-omurlu
```

Demetin ikinci parçası (`b`, `'b`'ye bağlı) yalnızca iç kapsamın içinde kullanılıyor ve o
kapsamla birlikte konu dışı kalıyor — `iceride` deftere düşüyor. Demetin ilk parçası (`ilk`,
`'a`'ya bağlı) ise dış kapsamda saklanıyor ve `iceride` bittikten sonra da kullanılabiliyor.
İki isimlendirilmiş ömür burada gerçekten farklı uzunlukta ömürlere karşılık geldi ve derleyici
bunu kabul etti, çünkü imza ikisi arasında hiçbir eşitlik istemedi. `'a` ve `oncelikli_ad`
imzasındaki tek `'a`, aynı harfi taşısalar da farklı işlevlerde farklı somut aralıklara denk
gelir — ad, imzanın kendi kapsamında geçerli bir etikettir, işlevler arasında paylaşılan bir
kayıt değildir.

#### Sınırlayıcı Ölçüm: Açıklama Bir Söz Değil, Bir İstektir

Açıklama yazmak, derleyiciye bir bilgi vermek gibi görünse de aslında bir **istek**: "dönen
referans en az `'a` kadar yaşasın" demenin biçimi. Derleyici bu isteği doğrulamak zorunda ve
istek gövdedeki koşumla tutmuyorsa yazım reddediliyor. Bu, açıklamayı bir belge notundan
ayıran şey: bir yorum satırı yanlış da olsa derlemeyi etkilemez, ama bir yaşam süresi
açıklaması yanlışsa derleme hiç gerçekleşmez.

`oncelikli_ad` işlevinin gövdesi `digeri.ad`'ı döndürmeye çalışsaydı — imza aynı kalıp yalnızca
son satır değiştirilseydi — derleyici bunu kabul etmezdi. İmza `'a`'yı yalnızca `oncelikli`
parametresine bağlıyor; `digeri`'nin kendi ömrü `'a` ile ilişkilendirilmemiş, yani derleyici
açısından `digeri`'nin çağrıdan sonra ne kadar yaşayacağı bilinmiyor. Dönen değerin `'a` kadar
yaşayacağı sözü verilmişken gövde bu sözü karşılamayan bir kaynaktan (`digeri`) değer
döndürürse, söz tutulamaz hâle gelir ve derleyici imzayı reddeder; reddin gerekçesi,
`digeri` için de `'a` açıklamasının eksik bırakılmış olmasıdır.

Burada derleyicinin elinde başka bir seçenek yok: `oncelikli`'nin çağrı sırasında ne kadar
yaşayacağı imzadan biliniyor, ama `digeri`'nin bilinmiyor. Derleyici, çağıranın `digeri` için
her zaman en az `'a` kadar yaşayan bir referans vereceğinden emin olamadığı sürece, gövdenin
`digeri`'den bir değer döndürmesine izin veremez — aksi hâlde bir çağıran, kısa ömürlü bir
`digeri` göndererek dönen referansın sahibinden uzun yaşamasına yol açabilirdi. Bu, önceki
derste kurulan sınırın (bir referans sahibinden uzun yaşayamaz) işlev sınırları arasında da
geçerli olduğunu gösteriyor.

Bu isteği karşılanabilir hâle getirmenin iki yolu var. Sahiplik ve Taşıma dersinde görülen
yaklaşım burada da geçerli olurdu: işlev referans yerine sahip olunan bir değer döndürseydi
(`digeri.ad.clone()` gibi), yaşam süresi sorunu hiç ortaya çıkmazdı, çünkü dönen değerin artık
hiçbir girdiye bağlı bir ömrü kalmazdı. Bu ders o yolu değil, referansı koruyan ikinci yolu
izliyor: iki parametreyi de aynı `'a`'ya bağlamak; böylece hem `oncelikli` hem `digeri` en az
`'a` kadar yaşayacağına söz veriyor ve gövde ikisinden herhangi birini döndürebiliyor.

```rust
// birlesik_omur.rs — istek karsilanabilir hale getirilince kabul ediliyor: iki parametre de 'a'yi tasiyor.

use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz { ad: ad.to_string(), defter: Rc::clone(defter) }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

// Simdi ikisi de 'a: donen deger her iki parametreden de gelebilir.
fn digerinin_adi<'a>(_oncelikli: &'a Iz, digeri: &'a Iz) -> &'a str {
    &digeri.ad
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    let a = Iz::yeni("a", &defter);
    let b = Iz::yeni("b", &defter);
    println!("{}", digerinin_adi(&a, &b));
}
```

```
b
```

`digerinin_adi` artık `digeri.ad`'ı döndürebiliyor, çünkü imza artık iki parametrenin de en
az `'a` kadar yaşayacağını söylüyor ve gövde bu sözü karşılıyor — hangi parametre
döndürülürse döndürülsün, söz tutuluyor. `oncelikli_ad` ile `digerinin_adi` arasındaki fark,
davranışta değil imzanın **kapsadığı sözde**: ilki yalnızca bir parametre için söz veriyordu,
ikincisi ikisi için de veriyor.

**YS5.** Bir yaşam süresi açıklaması, derleyicinin doğrulamak zorunda olduğu bir istektir.
Gövde, açıklamanın verdiği sözü tutmayan bir kaynaktan değer döndürürse yazım reddedilir;
söz genişletilip her iki kaynağı da kapsayacak hâle getirilince aynı gövde kabul edilir.

`digerinin_adi`'nin iki parametreyi de aynı `'a`'ya bağlaması bedelsiz değil. `oncelikli_ad`
çağrıldığında `digeri`'nin `oncelikli`'den daha kısa yaşaması hiç sorun değildi, çünkü açıklama
`digeri`'yi hiç kapsamıyordu. `digerinin_adi` çağrıldığında ise artık ikisi de en az `'a` kadar
yaşamak zorunda; çağıran taraf, ömrü daha kısa olan bir referansı `digerinin_adi`'ye veremez,
çünkü imza bunu izin vermiyor. Sözü genişletmek işlevi daha esnek hale getirmiyor, tam tersine
çağıranın uyması gereken koşulu sıkılaştırıyor. Bu, açıklamanın yalnızca "hangi bilgi
eklendiğini" değil, "eklenen bilginin çağırana ne yüklediğini" de belirlediğini gösteriyor —
en dar açıklama, gövdenin gerçekte ihtiyaç duyduğu kadarı, genellikle tercih edilen olan.

Bu üç ölçüm birlikte açıklamanın üç yüzünü gösterdi: `oncelikli_ad` bir ilişkiyi **yazdı**,
`ikisini_de_dondur` iki ilişkinin **bağımsız** kalabileceğini gösterdi, `digerinin_adi` ise
`oncelikli_ad`'ın **karşılayamadığı** ilişkinin, açıklama genişletilince **kabul edildiğini**
gösterdi.
Üçünde de açıklamanın kendisi hiçbir referansın ömrünü değiştirmedi; yalnızca kaynakta zaten
var olan ya da olması istenen bir ilişkiyi yazılı hâle getirdi ve derleyici bu yazının
tutarlılığını sınadı.

#### Özet

- Açık yaşam süresi açıklaması, bir işlev birden çok referans alıp içlerinden birini
  döndürdüğünde ve dönen referansın hangi girdiye bağlı olduğu kaynaktan çıkarılamadığında
  gerekir.
- Açıklama, referanslar arasında **var olan** bir ilişkiyi kaynağa yazar; herhangi bir
  referansın ömrünü uzatmaz ya da kısaltmaz; referans verilen değerler yine kendi **kapsam
  sonlarında** bitiyor.
- Bir imza birden çok adlandırılmış ömür taşıyabilir; her ad yalnızca imzanın kendi
  kapsamında geçerlidir ve farklı işlevlerdeki aynı ad birbirine bağlı değildir.
- Açıklama, derleyicinin doğrulamak zorunda olduğu bir istektir: dönen değer, açıklamanın söz
  verdiği kaynaktan gelmelidir.
- Sözü karşılamayan bir gövde reddedilir; söz genişletilip ilgili tüm kaynakları kapsayacak
  hâle getirilince aynı gövde kabul edilir, ama bu genişletme çağırana yüklenen koşulu da
  sıkılaştırır.

#### Sonraki Adım

Bu derste açıklamanın ne zaman **yazılması gerektiği**, neyi ifade ettiği ve karşılanmadığında
neden reddedildiği görüldü. Ama kursun önceki derslerindeki çoğu işlev — tek girdili, ya da
`self` alan yöntemler — hiç açık açıklama taşımıyordu ve yine de derlendi; bu işlevlerde
açıklama yazılmadığı hâlde bir ilişki zaten kurulmuş oluyordu. Sıradaki ders bu boşluğu
dolduruyor: derleyicinin yazılmayan açıklamayı hangi kurallarla türettiğini, bu kuralların
kaç imza biçimini kapsadığını ve hangi imzaların bu kuralların dışında kaldığını ölçüyor.

### Yaşam Süresi Çıkarım Kuralları

Source: https://academia.sh/tr/kurslar/sahiplik/yasam-suresi-cikarim-kurallari

Derleyicinin bir imzada yazılmayan yaşam süresi açıklamasını hangi kurallarla türettiği ölçülüyor. Aynı imza açık ve örtük biçimde yazılıp koşturuluyor ve ikisinin de aynı davranışı verdiği gösteriliyor; çıkarımın kapsamadığı imzada açıklamanın yine zorunlu kaldığı bir redd-kabul çiftiyle sınanıyor.

Önceki ders açık yazımın ne zaman gerektiğini ve neyi ifade ettiğini ölçtü. Ama kursun daha
önceki derslerinde geçen işlevlerin çoğu — tek girdi alıp bir referans döndüren, ya da `self`
üzerinden çalışan yöntemler — hiç açık açıklama taşımadı ve yine de derlendi. Bu ders o
boşluğu dolduruyor: derleyici, yazılmayan açıklamayı hangi kurallarla türetiyor ve bu
kuralların kapsamadığı imzalarda ne oluyor.

Bu soru M09/K01'in "yazılmayanın karşılığı ne" eksenine benziyor ama aynı şey değil: orada
ölçülen, yazılmayan bir tür bilgisinin derleyici tarafından nereden tamamlandığıydı; burada
ölçülen bir referansın ömrünün **nerede bittiği** — çıkarım kuralları yalnızca bu bilgiyi
kaynağa yazma zorunluluğunu kaldırıyor, bilginin kendisini değiştirmiyor. Eşzamanlılık
kursunun (M09/K03) sorduğu "koşan bir birim nasıl duracak" sorusu da burada geçerli değil;
bu ders hâlâ bir referansın geçerlilik aralığını ölçüyor, bir çalışma biriminin durmasını
değil.

Çıkarımın kendisi yeni bir bilgi kaynağı değil. Önceki derste kurulan ilke geçerliliğini
koruyor: derleyici hiçbir zaman tahmin yürütmüyor, yalnızca **her zaman aynı sonuca varacağı**
durumlarda yazımı kısaltıyor. Bir imza biçimi çıkarımın kapsamına girdiğinde, o biçimdeki her
imza için tek bir doğru okuma var demektir; girdiden çıktıya giden yol birden fazla olasılık
taşımıyor. Bu ders o kapsamın nerede başlayıp nerede bittiğini ölçüyor.

Bu, kaynağı okuyan bir kişi açısından da önemli bir sonuç doğuruyor: bir imzada açıklama
görünmüyorsa, bu iki farklı şeyi ifade edebilir. Ya işlevin dönen değerle hiçbir referans
ilişkisi yok, ya da ilişki var ama imza biçimi çıkarımın kapsadığı iki kalıptan birine giriyor.
Bu ikisi arasındaki fark, imzaya bakıp girdi sayısını ve `self`'in varlığını kontrol ederek
ayırt ediliyor — aşağıdaki iki ölçüm bu kontrolü somutlaştırıyor.

#### Üç Kural, İki Kolaylık

Bir imzada açıklama yazılmadığında derleyicinin varsayacağı ilişkiye **çıkarım (elision)**
deniyor. Rust'ın dil belirtimi bu varsayımı üç kuralla tanımlıyor. İlk kural her girdi
referansına kendi ayrı, adsız bir
ömür veriyor — bu her zaman geçerli ve kendi başına bir çıktı üretmiyor. İkinci kural, girdi
tam olarak bir referansa sahipse, o girdinin ömrünü bütün elenmiş çıktı referanslarına
atıyor. Üçüncü kural, girdiler arasında `&self` ya da `&mut self` varsa, `self`'in ömrünü
bütün elenmiş çıktı referanslarına atıyor.

İkinci ve üçüncü kural, pratikte açıklamayı gereksiz kılan kurallar — ilk kural yalnızca
girdi tarafını adlandırıyor, çıktıyı hiçbir girdiye bağlamıyor. Örneğin iki referans alıp
hiç referans döndürmeyen bir işlevde yalnızca ilk kural işliyor: her girdi kendi ayrı ömrünü
alıyor ve mesele orada bitiyor, çünkü elenecek bir çıktı yok. İkinci ve üçüncü kural devreye
ancak elenmiş bir çıktı referansı olduğunda giriyor ve bu çıktının hangi girdiye bağlanacağını
belirliyor.

İkinci kuralın "tam olarak bir girdi" koşulu, girdi **sayısına** değil girdideki **referans**
sayısına bakıyor. Bir işlev bir sayı ve bir referans birlikte alıyorsa, girdi listesi iki
öğe taşısa da ömür taşıyan girdi hâlâ tek — ikinci kural yine uygulanıyor. Aynı biçimde, bir
işlev tek bir referans alıp birden çok referans içeren bir demet döndürürse, elenmiş her
çıktı parçası da aynı tek girdinin ömrünü alıyor; kural "tek bir çıktıya" değil, "elenmiş
bütün çıktılara" uygulanıyor. Aşağıdaki iki ölçüm bu iki kolaylığı ayrı ayrı gösteriyor: önce tek girdili bir
işlev, sonra `&self` alan bir yöntem.

#### Ölçüm: Tek Girdili İmza

Bir işlev yalnızca bir referans alıp bir referans döndürüyorsa, ikinci kural devreye giriyor:
elenmiş tek girdinin ömrü, elenmiş çıktıya atanıyor. Aşağıda aynı işlev iki kez yazılıyor —
biri açıklamasız, biri açık `'a` ile — ve ikisi de aynı sonucu veriyor.

```rust
// cikarim_tek_girdi.rs — tek girdili imza: aciklama yazilmasa da (elision) ayni davranis.

struct Iz {
    ad: String,
}

// Ortuk: derleyici tek girdinin omrunu cikan referansa atiyor.
fn ilk_uc_harf(iz: &Iz) -> &str {
    &iz.ad[..3]
}

// Acik: ayni iliski elle yazildi.
fn ilk_uc_harf_acik<'a>(iz: &'a Iz) -> &'a str {
    &iz.ad[..3]
}

fn main() {
    let deger = Iz { ad: "kapsam-1".to_string() };
    println!("ortuk -> {}", ilk_uc_harf(&deger));
    println!("acik  -> {}", ilk_uc_harf_acik(&deger));
}
```

```
ortuk -> kap
acik  -> kap
```

`ilk_uc_harf` ve `ilk_uc_harf_acik` aynı gövdeyi taşıyor ve aynı çıktıyı veriyor; aralarındaki
tek fark kaynaktaki açıklamanın görünürlüğü. Derleyici, birincisini derlerken ikincisiyle
aynı ilişkiyi kendisi kuruyor — girdi tek olduğu için başka bir ihtimal de yok: dönen
referans ya `iz`'den geliyor ya da hiç yok.

**YS6.** Çıkarım kuralları, derleyicinin **her zaman** aynı sonuca varacağı durumlarda
açıklamayı gereksiz kılıyor. Tek girdili bir imzada dönen referansın hangi girdiye bağlı
olacağı konusunda gerçek bir belirsizlik yok — girdi zaten bir tane.

Bu, önceki dersteki `oncelikli_ad` işleviyle karşılaştırıldığında daha net görülüyor:
`oncelikli_ad` iki girdi aldığı için açıklamasız yazılamazdı, çünkü dönen referansın
`oncelikli`'den mi `digeri`'den mi geldiği kaynaktan çıkarılamazdı. `ilk_uc_harf` tek girdi
aldığı için aynı belirsizlik hiç oluşmuyor — çıkarım kuralı burada gerçek bir seçim yapmıyor,
yalnızca zaten tek olan seçeneği kaynağa yazmaktan kurtarıyor.

#### Ölçüm: `self` Alan Yöntem

Üçüncü kural, bir yöntem `self`'i ve başka referanslar alsa bile, elenmiş çıktıyı hep
`self`'in ömrüne bağlıyor. Bu, kursun önceki derslerinde görülen birçok yöntemin neden hiç
açıklama taşımadığını açıklıyor.

```rust
// cikarim_self.rs — &self alan yontem: cikan referans self'e baglaniyor, aciklama yazilmasa da.

struct Iz {
    ad: String,
}

impl Iz {
    // Ortuk: self'in omru cikan referansa atanir.
    fn adi(&self) -> &str {
        &self.ad
    }
}

struct IzAcik {
    ad: String,
}

impl IzAcik {
    // Acik: ayni atama elle yazildi.
    fn adi<'a>(&'a self) -> &'a str {
        &self.ad
    }
}

fn main() {
    let deger = Iz { ad: "kapsam-2".to_string() };
    let acik = IzAcik { ad: "kapsam-2".to_string() };
    println!("ortuk -> {}", deger.adi());
    println!("acik  -> {}", acik.adi());
}
```

```
ortuk -> kapsam-2
acik  -> kapsam-2
```

`Iz::adi` ile `IzAcik::adi` aynı davranışı veriyor. Burada dikkat çeken şey, yöntemin `self`
dışında başka bir referans alsaydı bile sonucun değişmeyeceği — üçüncü kural yalnızca
`self`'e bakıyor, diğer girdileri hiç hesaba katmıyor. Bu, ikinci kuraldan farklı bir kaynağa
dayanan aynı sonuç: derleyici, `self` alan bir yöntemde dönen referansın neredeyse her zaman
`self`'in bir parçası olduğunu varsayıyor ve bu varsayım yeterince güvenilir kabul edildiği
için kurala dönüştürülmüş.

Bu iki kural bir arada, kursun önceki derslerinde görülen yöntemlerin çoğunun neden hiç
açıklama taşımadığını da açıklıyor: bir tipin kendi alanına referans döndüren yöntemleri
`&self` alıyordu ve üçüncü kural devreye giriyordu; bir değeri okuyup türetilmiş bir referans
döndüren serbest işlevler çoğunlukla tek girdiliydi ve ikinci kural devreye giriyordu. Açık
açıklamanın gerçekten göründüğü yer, önceki derste olduğu gibi, birden fazla girdinin
`self` olmadan bir arada bulunduğu imzalardı.

**YS7.** İki farklı kural, iki farklı imza biçiminde aynı sonucu üretiyor: tek girdili
işlevlerde girdinin kendisi, `self` alan yöntemlerde `self`'in kendisi, çıktının ömrünü
belirliyor. Bu iki biçimde açıklama hiç yazılmasa da imza kabul ediliyor; ikisinin de ortak
noktası, dönen referansın gidebileceği tek bir yerin olması.

#### Bir İmzayı Okumanın Sırası

Yukarıdaki iki ölçüm birlikte, bir imzaya bakıp açıklamanın gerekip gerekmediğini belirlemenin
sırasını da veriyor. Önce girdilerdeki referans sayısı sayılıyor: hiç referans yoksa ya da
elenecek bir çıktı referansı yoksa, ilk kural tek başına yetiyor ve mesele kapanıyor. Girdide
tam olarak bir referans varsa, ikinci kural devreye giriyor ve çıktı ona bağlanıyor —
`ilk_uc_harf` bu yola giriyor. Girdide birden fazla referans varsa, sıradaki soru `self`'in
olup olmadığı: varsa üçüncü kural devreye giriyor ve çıktı `self`'e bağlanıyor — `Iz::adi` bu
yola giriyor. Birden fazla referans var ve `self` yoksa, üç kuraldan hiçbiri tek bir sonuca
varamıyor ve açık açıklama zorunlu hâle geliyor — `daha_uzun_olan` bu son duruma düşüyor.

Bu sıralama, derleyicinin kendi iç işleyişinden çok, bir okuyucunun bir imzaya bakıp açıklama
bekleyip beklemeyeceğini hızlıca kestirmesi için kullanışlı bir kısayol. Kurs boyunca görülen
işlevlerin çoğu ilk iki basamakta çözülüyor; açık açıklamanın göründüğü yerler, tam da bu
sıralamanın son basamağına düşen, birden fazla eşit ağırlıklı referans taşıyan imzalar oluyor.

Bu sıralamanın kendisi bir araç ya da bir doğrulayıcı gerektirmiyor — üç madde ezberlenip
herhangi bir imzaya elle uygulanabiliyor. Bu da yaşam süresiyle ilgili önceki ölçümlerle aynı
örüntüyü tekrarlıyor: kaynak, kendi başına, çalıştırılmadan okunabilir bir bilgi taşıyor.
Farkı, burada okunanın bir referansın aralığı değil, o aralığın **yazılıp yazılmadığı** kararı
olması.

#### Sınırlayıcı Ölçüm: Çıkarım Kolaylıktır, Kural Değildir

Çıkarım kuralları üç maddeyle sınırlı ve bu üç maddenin kapsamadığı imzalar var. En açık
örnek, `self` içermeyen ve birden fazla referans alan bir işlev: ne ikinci kural (tek girdi
yok), ne üçüncü kural (`self` yok) devreye giriyor. Böyle bir işlevde dönen referansın hangi
girdiye bağlı olduğu konusunda derleyicinin kendiliğinden varacağı tek bir sonuç yok —
birinci kural her girdiye kendi ayrı ömrünü veriyor ve hiçbirini çıktıya atamıyor.

Önceki derste görülen iki referanslı, `self`'siz işlev (`oncelikli_ad`) tam olarak bu
durumdaydı ve açık `'a` taşıyordu — o derste açıklama, iki girdiden yalnızca birine bağlanan
dar bir söz kuruyordu. Aynı sınır burada yeni bir örnekle, bu kez her iki girdinin de gerçekten
dönebildiği bir durumla sınanıyor: iki `Iz` referansı alıp adı daha uzun olanın dilimini
döndüren bir işlev, açıklamasız yazılırsa derleyici hangi girdinin döndürüldüğünü
belirleyemediği için reddediyor. Gövde, çalışma zamanındaki bir karşılaştırmaya göre `x`'i de
`y`'yi de döndürebiliyor — bu da girdilerin eşit ağırlıklı olduğunu, birinin diğerine göre
öncelikli olmadığını gösteriyor. Kabul edilen yazım ise açık `'a` ile ikisini de aynı ömre
bağlıyor.

```rust
// cikarim_disi.rs — cikarimin kapsamadigi imza: aciklama yazilmadan derlenmiyor, yazilinca derleniyor.

struct Iz {
    ad: String,
}

fn daha_uzun_olan<'a>(x: &'a Iz, y: &'a Iz) -> &'a str {
    if x.ad.len() >= y.ad.len() { &x.ad } else { &y.ad }
}

fn main() {
    let a = Iz { ad: "kisa".to_string() };
    let b = Iz { ad: "daha-uzun-ad".to_string() };
    println!("{}", daha_uzun_olan(&a, &b));
}
```

```
daha-uzun-ad
```

`daha_uzun_olan`'ın açıklamasız hâli üç kuraldan hiçbirine uymuyor: iki girdi var, `self`
yok. Derleyici, dönen referansın `x`'ten mi `y`'den mi geldiğini belirleyemediği için imzayı
reddediyor; kabul edilen yazım, önceki dersteki `digerinin_adi` işlevinde görülen çözümün
aynısını uyguluyor — iki girdiyi de aynı `'a`'ya bağlamak. Yukarıdaki koşum bu kabul edilen
biçimle çalışıyor ve iki adı karşılaştırıp uzun olanı döndürüyor.

`digerinin_adi` ile `daha_uzun_olan` arasındaki fark, kabul edilme gerekçesinde değil, dönüş
kararının **ne zaman** belli olduğunda: `digerinin_adi`'de hangi parametrenin döndürüleceği
işlevin gövdesinde sabitti, `daha_uzun_olan`'da bu karar her çağrıda yeniden, çalışma
zamanındaki bir karşılaştırmayla veriliyor. İki durumda da açıklama aynı işi görüyor —
dönebilecek her kaynağı önceden kapsıyor — çünkü derleme zamanında hangi dalın seçileceği
bilinmiyor; açıklama olası bütün yolları kapsamak zorunda, yalnızca gerçekte izlenen yolu
değil.

**YS8.** Çıkarım kuralları bir **kolaylıktır**, dilin her imzayı derleyebileceği anlamına
gelmez. Üç kuraldan hiçbiri bir imzaya uymadığında açıklama yine zorunlu; kural yalnızca
**ne zaman gerekmediğini** belirliyor, her zaman gerekmeyeceğini değil.

Bu sınır, önceki derste kurulan ilkeyle aynı köke dayanıyor: derleyici bir açıklamayı yalnızca
kaynaktan **tek bir doğru okuma** çıkıyorsa atlıyor. `daha_uzun_olan` gibi iki eşit ağırlıklı
girdisi olan bir işlevde bu tek okuma yok — `x` ve `y` aynı tipte, aynı konumda, ikisi de
dönebilir. Üç kural da bu belirsizliği çözecek bir varsayım içermiyor, çünkü herhangi bir
varsayım bazı doğru programları reddedip bazı yanlış olanları kabul edebilirdi. Rust bu
riski almak yerine yazımı reddediyor ve kararı geliştiriciye bırakıyor; bu da açıklamanın
kolaylık değil güvence olduğu yerde neden hâlâ zorunlu kaldığını gösteriyor.

#### Özet

- Rust'ın çıkarım kuralları, yaşam süresi açıklamasının bazı imza biçimlerinde
  yazılmasını gereksiz kılıyor; bunlardan ikisi kursta ölçüldü: tek girdili işlevler ve
  `self` alan yöntemler.
- Tek girdili bir işlevde elenmiş girdinin ömrü elenmiş çıktıya atanıyor; `self` alan bir
  yöntemde bu atama girdi sayısından bağımsız olarak hep `self`'e yapılıyor.
- Aynı imzanın açık ve örtük biçimleri, ölçülen iki durumda da birebir aynı davranışı verdi; iki biçimde de değerler **kapsam
  sonunda** bitti.
- Bu ders M09/K01'in yazılmayan tür bilgisini ölçen ekseninden farklı: burada ölçülen bir
  referansın ömrünün nerede bittiği, tür bilgisinin nereden tamamlandığı değil.
- Üç kuralın kapsamadığı imzalarda (birden çok girdi, `self` yok) açıklama zorunlu kalıyor;
  kapsamayan bir imza açıklamasız yazılırsa reddediliyor.
- Çıkarım, derleyicinin bir imzadan **tek bir doğru okuma** çıkardığı durumlarda geçerli;
  birden fazla eşit ağırlıklı olasılık varsa derleyici bir varsayımda bulunmak yerine yazımı
  reddediyor.

#### Sonraki Adım

Bu derste çıkarımın hangi imzaları kapsadığı ve hangilerini kapsamadığı görüldü — kapsayan
imzalarda açıklama gereksizdi, kapsamayanlarda hâlâ zorunluydu ve bu zorunluluk işlev
parametreleri arasında kuruldu. Ama aynı ihtiyaç bir yapının kendi alanında da ortaya
çıkabilir: bir yapı bir referans tutuyorsa, o yapının kendisi referans verdiği veriden daha
uzun yaşayamaz ve bu koşulun da bir açıklamayla yazılması gerekir. Sıradaki ders bu koşulu,
aynı veriyi bir yapıya taşıyarak ve ödünç vererek tutan iki kurguyu karşılaştırarak ölçüyor.

### Yapılarda Referans Tutma

Source: https://academia.sh/tr/kurslar/sahiplik/yapilarda-referans-tutma

Bir yapının alanında referans tutmanın yapının kendi ömrüne getirdiği koşul ölçülüyor: yapı, referans verdiği veriden uzun yaşayamaz. Aynı veri bir yapıya taşınarak ve ödünç verilerek tutuluyor; taşınan alanın yapıyla birlikte bittiği, ödünç verilen verinin yapıdan sonra bittiği koşturularak karşılaştırılıyor.

Önceki ders çıkarım kurallarının işlev parametreleri arasında kapsadığı ve kapsamadığı
imzaları ölçtü. Ama açık açıklama yalnızca işlev imzalarında değil, bir yapının kendi
tanımında da gerekebilir: bir yapının alanı bir referans tutuyorsa, yapının kendisi bu
referansın ömrüne bağlı hâle geliyor. Bu ders bu koşulu, aynı veriyi bir yapıya iki farklı
yoldan — taşıyarak ve ödünç vererek — tutan iki kurguyu karşılaştırarak ölçüyor.

Eşzamanlılık kursunun (M09/K03) sorduğu soru burada da farklı: orada koşan bir birimin
durması ölçülüyordu, burada bir yapının içindeki bir alanın bitiş noktası ölçülüyor. Yığıt ve
Öbek dersinde kurulan dört bitiş sınıfı burada yeniden karşımıza çıkıyor, ama bu kez iki
farklı alan türü üzerinden karşılaştırılıyor.

Bu konu boyunca ölçülen şey hep aynı soruydu: bir referansın geçerlilik aralığı
nereden okunuyor. Yaşam Süresi Kavramı dersi bu aralığı bir referans için, Açık Yaşam Süresi
Açıklamaları ve Yaşam Süresi Çıkarım Kuralları dersleri bunu bir işlev imzası için ölçtü. Bu
son ders aynı soruyu bir yapı tanımına taşıyor: bir yapının **kendi** ömrü, taşıdığı bir
referansın ömrüyle nasıl ilişkileniyor.

#### İki Yol: Taşımak ve Ödünç Almak

Bir yapı, bir alanına bir değer koymak istediğinde iki seçeneği var: değeri **taşıyabilir**
(alan sahip olur) ya da değere bir **referans tutabilir** (alan yalnızca ödünç alır). Sahiplik
ve Taşıma dersinde görülen taşıma kuralı ilk seçenekte geçerli — alan, kendi başına sahip
olunan sıradan bir değer gibi davranıyor. İkinci seçenek yeni bir soru açıyor: yapının kendisi
ne kadar yaşayabilir, referans verdiği veriden daha uzun yaşayabilir mi?

Cevap hayır ve bu, derleyicinin bir yapı tanımında zorunlu kıldığı bir kural. Bir yapının
alanı bir referans tutuyorsa, yapının kendi tanımı bir yaşam süresi parametresi taşımak
zorunda — bu parametre, yapının kendisinin en fazla ne kadar yaşayabileceğini, referans
verdiği veriyle ilişkilendiriyor.

Bu, önceki iki derste işlev imzaları için kurulan kuralın yapı tanımlarındaki karşılığı.
Orada bir işlevin dönen referansı hangi girdiye bağlı olduğunu söylemek zorundaydı; burada
bir yapının kendisi, taşıdığı referansın hangi kaynağa bağlı olduğunu söylemek zorunda. Fark,
ilişkinin nerede kurulduğu: bir işlev çağrısının ömründe değil, bir yapı örneğinin ömründe.
Bu örnek ne kadar uzun yaşarsa yaşasın — bir değişkende, bir başka yapının alanında, bir
koleksiyonun içinde — taşıdığı referansın kaynağından daha uzun yaşayamayacağı garantisi
değişmiyor.

#### Ölçüm: Taşınan Alan Yapıyla Birlikte Bitiyor, Ödünç Alınan Veri Yapıdan Sonra Bitiyor

Aşağıdaki ölçüm iki yapı tanımlıyor: `SahipYapi` bir `Iz` değerine sahip oluyor, `OduncYapi`
bir `Iz` değerine yalnızca referans tutuyor ve bu yüzden `<'a>` parametresi taşıyor. İki yapı
da aynı çekirdek (`Iz`, `Defter`, `Drop`) üzerinde çalışıyor; ölçülen fark yalnızca alanın
taşınıp taşınmadığında.

```rust
// yapida_referans.rs — yapida tasinan alan ile odunc alinan alanin bitis noktasi karsilastirmasi.

use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz { ad: ad.to_string(), defter: Rc::clone(defter) }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

fn okunan(defter: &Defter) -> Vec<String> {
    defter.borrow().clone()
}

fn yeni_olanlar(defter: &Defter, onceki: usize) -> String {
    let hepsi = okunan(defter);
    hepsi[onceki..].join(", ")
}

struct SahipYapi {
    icerik: Iz,
}

struct OduncYapi<'a> {
    icerik: &'a Iz,
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));

    // Tasinan alan: yapi bitince biter.
    let s0 = okunan(&defter).len();
    {
        let tasinan = Iz::yeni("tasinan-alan", &defter);
        let yapi = SahipYapi { icerik: tasinan };
        println!("SahipYapi icindeki alan -> {}", yapi.icerik.ad);
        println!("SahipYapi ayaktayken -> [{}]", yeni_olanlar(&defter, s0));
    }
    println!("SahipYapi bitince    -> {}", yeni_olanlar(&defter, s0));

    // Odunc alinan alan: yapi biter, veri hala yasar.
    let o0 = okunan(&defter).len();
    {
        let odunc_veri = Iz::yeni("odunc-veri", &defter);
        {
            let yapi = OduncYapi { icerik: &odunc_veri };
            println!("OduncYapi icinde     -> {}", yapi.icerik.ad);
        }
        println!("OduncYapi bitince    -> [{}]", yeni_olanlar(&defter, o0));
    }
    println!("odunc-veri bitince   -> {}", yeni_olanlar(&defter, o0));
}
```

```
SahipYapi icindeki alan -> tasinan-alan
SahipYapi ayaktayken -> []
SahipYapi bitince    -> tasinan-alan
OduncYapi icinde     -> odunc-veri
OduncYapi bitince    -> []
odunc-veri bitince   -> odunc-veri
```

`SahipYapi` bölümünde `tasinan` değeri `yapi`'nin alanına **taşınıyor** ve o andan sonra
kendi başına bir bağlaması kalmıyor — yalnızca `yapi.icerik` üzerinden erişilebiliyor. `yapi`
ayaktayken defter boş; `yapi` kapsamı kapanınca `tasinan-alan` deftere düşüyor. Bu, Sahiplik
ve Taşıma dersinde ölçülen "yapı alanına taşınan değer" kalıbının bir tekrarı: alan, yapının
kendisiyle birlikte bitiyor.

`OduncYapi` bölümünde ise `odunc_veri` kendi bağlamasında kalıyor ve `yapi` yalnızca ona bir
referans tutuyor. `yapi`'nin kendi iç kapsamı kapandığında defter **hâlâ boş** — `OduncYapi`
örneğinin bitişi hiçbir kayıt üretmiyor, çünkü `&'a Iz` `Drop` uygulamıyor. `odunc_veri`
kendisi ancak kendi kapsamı (dıştaki blok) kapanınca deftere düşüyor — bu da `OduncYapi`
örneğinin bitişinden **sonra**.

İki bölümün ortak noktası, ikisinde de yalnızca bir kaydın oluşması: `SahipYapi` bölümünde
tek kayıt `tasinan-alan`, `OduncYapi` bölümünde tek kayıt `odunc-veri`. `OduncYapi`'nin
kendisi hiçbir zaman deftere düşmüyor — çünkü yapının kendisi `Drop` uygulamıyor, yalnızca
içindeki referans aracılığıyla başka bir yerdeki `Iz` değerine bakıyor. Bu, referans tutan bir
yapının kendi bitişinin gözlemlenebilir bir yan etkisi olmadığını gösteriyor; gözlemlenebilir
olan yalnızca referans verdiği verinin bitişi ve bu bitiş hiçbir zaman yapının kendi
bitişinden önce gelmiyor — en erken, ikisinin aynı kapsamda birlikte bitmesiyle çakışabiliyor.

**YS9.** Bir yapının alanına taşınan bir değer, yapının kendisiyle birlikte biter. Bir yapının
alanında tutulan bir referansın verisi ise yapıdan **sonra** biter — yapının kendisi hiçbir
zaman kendi verisinden uzun yaşamıyor, ama referans verilen veri yapıdan daha uzun yaşayabilir
ve genellikle de yaşıyor.

#### Yapının Kendi Yöntemi Yine Çıkarımla Yazılıyor

`OduncYapi<'a>` bir yaşam süresi parametresi taşısa da, üzerine yazılan yöntemler bu
parametreyi mutlaka tekrarlamak zorunda değil. Önceki ders kurulan çıkarım kuralları burada
da geçerli: `&self` alan bir yöntemin dönen referansı, üçüncü kural gereği `self`'in kendi
ömrüne bağlanıyor ve bu, `'a`'nın ayrıca yazılmasını gereksiz kılıyor. Bu, iki dersin
birbirinden bağımsız olmadığını, aynı kuralların farklı bağlamlarda tekrar tekrar
uygulandığını gösteren somut bir örnek.

```rust
// yontem_cikarimi.rs — omur parametresi tasiyan yapinin kendi yontemi hala cikarimla yaziliyor.

use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz { ad: ad.to_string(), defter: Rc::clone(defter) }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

struct OduncYapi<'a> {
    icerik: &'a Iz,
}

impl<'a> OduncYapi<'a> {
    // Aciklamasiz: cikarimin ucuncu kurali (self) burada da gecerli.
    fn ad(&self) -> &str {
        self.icerik.ad.as_str()
    }
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    let veri = Iz::yeni("paylasilan-veri", &defter);
    let yapi = OduncYapi { icerik: &veri };
    println!("{}", yapi.ad());
}
```

```
paylasilan-veri
```

`impl<'a> OduncYapi<'a>` bloğu `'a`'yı tanıtmak zorunda — yapı tanımı onu gerektiriyor — ama
`fn ad(&self) -> &str` imzası kendi başına hiçbir açıklama taşımıyor. Derleyici burada da
önceki dersteki gibi davranıyor: `&self` tek referans girdisi olduğu için üçüncü kural
uygulanıyor ve dönen `&str`, `self`'in ömrüne bağlanıyor. `self`'in kendisi `OduncYapi<'a>`'ya
bir referans olduğundan, dönen dilim de dolaylı olarak `'a`'nın sınırları içinde kalıyor —
ama bu ilişki `ad` yönteminin kendi imzasında hiç yazılmıyor, çünkü çıkarım onu zaten
karşılıyor.

Bu ayrım, `'a`'nın nerede tanımlandığı ile nerede **kullanıldığı** arasındaki farkı gösteriyor.
`'a`, yapının tanımında ve `impl` bloğunun başlığında görünmek zorunda, çünkü alanın kendisi
ona bağlı. Ama bir yöntemin dönen değeri her zaman `self` üzerinden erişiliyorsa, o yöntemin
kendi imzası `'a`'yı tekrar yazmadan da doğru davranıyor — çıkarım kuralı burada tek bir girdi
(`self`) üzerinden çalışıyor, `'a`'nın kendisiyle hiç ilgilenmiyor. `'a`'nın açıkça yazılması
gereken yer, bir yöntemin dönen referansı `self` **dışında** bir kaynağa (örneğin yönteme ayrı
bir parametre olarak verilen başka bir referansa) bağlandığında ortaya çıkardı; bu, önceki
dersin sınırlayıcı ölçümünün burada da geçerli olduğu anlamına geliyor.

**YS10.** Bir yapı tanımı yaşam süresi parametresi taşıması, o yapı üzerindeki her yöntemin
de açık açıklama taşıması gerektiği anlamına gelmiyor. Çıkarım kuralları yapı yöntemlerinde
de işliyor; parametre yalnızca yapının **tanımında**, alanın kendisi için gerekiyor.

#### Sınırlayıcı Ölçüm: Yapı Tanımı Yaşam Süresi Parametresi Olmadan Yazılamaz

`OduncYapi` tanımı `<'a>` parametresi olmadan yazılamıyor. `icerik: &Iz` biçiminde, hiçbir
yaşam süresi belirtmeden yazılan bir alan derleyici tarafından reddediliyor, çünkü yapı
tanımı referansın hangi kaynağa bağlı olduğunu ve yapının o kaynaktan daha uzun
yaşamayacağını hiçbir yerde söylemiyor. Bu, önceki iki derste görülen kalıbın yapı
tanımlarındaki karşılığı: bir referans, ilişkisi kaynağa yazılmadan var olamıyor.

Burada çıkarım kuralları hiç devreye girmiyor — önceki ders görülen üç kural yalnızca işlev
imzalarındaki elenmiş referanslar için tanımlanmıştı, yapı alanları için değil. Bir yapının
alanı, girdi ya da çıktı değil; yapı her çağrıldığında yeniden değerlendirilen bir imza değil,
kendi başına duran bir veri düzeni. Derleyicinin burada varsayabileceği "tek doğru okuma" da
yok: bir alan referans taşıyorsa, o referansın kaynağı yapının **dışında** bir yerde olmak
zorunda ve bu kaynağın kim olduğu yalnızca yazan kişi tarafından bilinebilir bir bilgi.

Kabul edilen yazım yukarıdaki `OduncYapi<'a>` — `<'a>` parametresi yapının kendisine
ekleniyor, alan `&'a Iz` oluyor ve derleyici bu ilişkiyi doğruluyor: `OduncYapi`'nin herhangi
bir örneği, `icerik`'in işaret ettiği veriden daha uzun yaşayamaz. Yukarıdaki ölçüm bu sınırın
içinde kaldı — `yapi` her zaman `odunc_veri`'den önce bitti, hiç sonra değil. `yapi`
örneğinin kendi iç kapsamının dışına taşınmaya çalışıldığını, döndürüldüğünü ya da dış
kapsamdaki bir değişkene atandığını düşünelim: bu derlenmezdi, çünkü örneğin taşıdığı
referans `odunc_veri`'den daha uzun yaşayamaz — kısıt, Ödünç Denetleyicisi dersinde koşturulan
sınırın yapı alanlarındaki biçimi.

**YS11.** Bir yapı, referans taşıyan bir alana sahipse, yaşam süresi parametresi olmadan
tanımlanamaz. Parametre eklenip ilişki yazılınca yapı kullanılabilir hâle geliyor, ama bu
yapının hiçbir örneği kendi referans verdiği veriden uzun yaşayamıyor — parametre bu sınırı
kaldırmıyor, yalnızca kaynağa yazıyor.

#### İki Kurgu, Bir Tasarım Kararı

`SahipYapi` ile `OduncYapi` arasındaki seçim bir doğruluk sorunu değil, bir tasarım kararı.
Taşınan alan yapıyı veriden bağımsız kılıyor: `SahipYapi` bir kez kurulduktan sonra, verinin
başka bir yerde yaşayıp yaşamadığını umursamadan taşınabiliyor, döndürülebiliyor, uzun süre
saklanabiliyor. Bunun bedeli bir kopya ya da bir taşıma — veri artık yalnızca o yapıya ait.

Ödünç alınan alan ise veriyi paylaşmayı mümkün kılıyor: aynı `Iz` değeri hem kendi bağlamasında
kullanılabiliyor hem `OduncYapi` üzerinden okunabiliyor, üstelik bir kopya çıkarmadan. Bunun
bedeli de yapının kendi ömrünün veriye bağlanması — `OduncYapi`, verisinden daha uzun
yaşayamadığı için, dönüş değeri olarak kullanılması ya da uzun süre saklanması genellikle daha
kısıtlı. Hangi kurgunun seçileceği, yapının ne kadar süre yaşayacağına ve verinin başka
yerlerde de kullanılıp kullanılmayacağına bağlı.

Bu iki seçenek arasında üçüncü bir yol yok — bir alan ya sahip oluyor ya ödünç alıyor,
ikisinin ortası bulunmuyor. Bir alanın ödünç aldığı veri üzerinde yazma yetkisi de olabilir
(`&'a mut Iz`), ama bu da hâlâ ödünç alma kategorisinde kalıyor: yapı yine veriye sahip
olmuyor, yalnızca üzerinde değiştirme izni taşıyan bir referans tutuyor ve aynı yaşam süresi
koşuluna tabi oluyor. Kursun ilerleyen kısmında görülecek paylaşımlı sahiplik araçları
(öbekte tekil sahiplik, referans sayımı) bu iki seçeneğin ortasında duran üçüncü bir yol gibi
görünebilir, ama aslında değil — onlar da temelde birer sahiplik biçimi, yalnızca sahiplik
kuralının nasıl uygulandığı farklılaşıyor. Referans tutmak, verinin **hiçbir zaman** yapıya
geçmediği tek durum olarak kalıyor.

#### Özet

- Bir yapının alanı bir referans tutuyorsa, yapı tanımı bir yaşam süresi parametresi taşımak
  zorundadır; bu parametre olmadan yazılan tanım reddedilir.
- Bir yapının alanına taşınan bir değer, yapının kendisiyle birlikte biter: ömrü
  **taşındığı yerde** bitiyor.
- Bir yapının alanında tutulan bir referansın verisi, yapının kendisinden sonra biter —
  yapı asla verisinden uzun yaşayamaz.
- Yaşam süresi parametresi bu sınırı kaldırmaz, yalnızca kaynağa yazar; parametre eklenince
  bile bir yapı örneği kendi referans verdiği veriden uzun yaşayamaz.
- Taşınan alanla ödünç alınan alan arasındaki seçim bir tasarım kararıdır: biri yapıyı
  veriden bağımsız kılar, öbürü veriyi paylaşmayı mümkün kılar.
- Yaşam süresi parametresi yalnızca yapının tanımında gereklidir; parametreyi taşıyan bir
  yapının yöntemleri, çıkarım kuralları uyduğu sürece kendi başına açıklama taşımayabilir.

#### Sonraki Adım

Bu kursun ilk iki konusu boyunca bir değer bir yapıya ya taşındı ya ödünç verildi ve her iki
durumda da o değerin **tek bir sahibi** vardı — taşınan alanın sahibi yapıydı, ödünç verilen
verinin sahibi kendi kapsamıydı; ödünç alınan durumda bile sahiplik hiç bölünmedi, yalnızca
geçici olarak paylaşıldı. Sıradaki konu bu varsayımı kaldırıyor: bir değerin sahibi birden
çok olabilir mi ve bu durumda "bitiş" ne anlama gelir? Öbekte tekil sahiplikle başlayan bu
bölüm, önce özyinelemeli tipleri mümkün kılan tek bir öbek sahipliğini, sonra referans
sayımıyla gerçek anlamda paylaşılan sahipliği ölçüyor.

## Paylaşımlı Sahiplik

Öbekte tekil sahipliğin özyinelemeli tipleri mümkün kılması, sayacın paylaşılan bir değerin ömrünü belirlemesi, aynı sayacın iş parçacıkları arasında atomik biçimi, ödünç denetiminin çalışma zamanına taşınması, ve iki değerin birbirini tutmasıyla ömrün hiç bitmemesi.

### Öbekte Tekil Sahiplik

Source: https://academia.sh/tr/kurslar/sahiplik/obekte-tekil-sahiplik

Bir değerin öbekte yaşarken de tek bir sahibi kalabildiği, kabıyla birlikte biten bir değerin kabın kendi sırasına bağlı olduğu ve bu tekilliğin kendine referans veren bir tipi mümkün kıldığı ölçülüyor.

Yapılarda Referans Tutma dersi, bir yapının bir veriyi ya taşıdığını ya ödünç aldığını, iki
durumda da tek bir sahibin bulunduğunu ölçerek kapandı. Bu dersin sorusu tam o varsayımı hedef
alıyor: bir değerin sahibi birden çok olabilir mi? Yanıtın kendisi henüz gelmiyor — önce
sahiplik **sayısı** değil, sahip olunan değerin **nerede** durduğu değişiyor. Bu ara adım
gerekli, çünkü paylaşımlı sahipliğin nasıl ölçüleceğini anlamak için önce tek sahipli bir
değerin öbekte nasıl davrandığını bilmek gerekiyor. Ölçü ekseni değişmiyor: burada da bir
değerin nerede bittiği soruluyor, Eşzamanlılık kursundaki (M09/K03) gibi koşan bir birimin
nasıl duracağı değil.

Kursun açılış dersi, bir değerin yığıtta mı öbekte mi durduğunu M01/K01 ve M09/K05'in
üçüncü tekrarı olarak ele almıştı; bellek kuramı orada kapandı, burada yeniden açılmıyor.
Aynı derste dört sınıf kuruldu: bir değer kapsam sonunda, taşındığı yerde, açık bir
çağrıyla ya da bir kabıyla birlikte biter. Bu dersin sorduğu şey şu: bir değer öbekte
durduğunda, bu dört sınıftan hangisine giriyor ve sahiplik kuralı hâlâ aynı mı kalıyor?
`Box`, bir değeri öbeğe taşıyan ama sahiplik sayısını hiç değiştirmeyen bir kaptır — bu
dersin ölçtüğü ilk şey budur.

#### Kap da Bir Sınıf, Ama İçindeki Tek

"Kabıyla birlikte" bitişi tek bir biçimde gelmiyor. Bir liste birden çok değeri aynı anda
taşır; `Box` ise tam olarak bir değeri taşır. İkisi de kap sınıfına girer, ikisinde de
içerik kapla birlikte biter, ama kabın kendi bitiş sırası aynı değildir.

Bu dersin ölçümü de kursun açılışında kurulan `Iz`/`defter` düzeneğini kullanıyor: her
`Iz` değeri bırakıldığında kendi adını deftere ekliyor, bunu sağlayan `Drop` uygulaması
burada yeniden yazılmıyor, kesiti alınıyor. Aşağıdaki koşum, aynı kapsam içinde üç öğeli
bir listeyle tek bir `Box` değerini bir arada tutuyor ve kapsam kapanırken defterin aldığı
sırayı basıyor.

**PS1.** — "öbekteki tekil değerin listeden önce bittiği" iddiası, aşağıdaki koşumun
`bitis sirasi` satırıyla doğrulanıyor: `obekteki-tekil` adı, listenin üç elemanından önce
geliyor.

```rust
// kap_siniflari.rs — kabiyla birlikte sinifi: liste ve obekteki tekil deger
use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz {
            ad: ad.to_string(),
            defter: Rc::clone(defter),
        }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    {
        let mut liste = Vec::new();
        liste.push(Iz::yeni("liste-1", &defter));
        liste.push(Iz::yeni("liste-2", &defter));
        liste.push(Iz::yeni("liste-3", &defter));
        let _obekteki = Box::new(Iz::yeni("obekteki-tekil", &defter));
        println!("kap dolu iken defter uzunlugu: {}", defter.borrow().len());
    }
    let kayit = defter.borrow();
    println!("bitis sirasi: {}", kayit.join(", "));
}
```

```
kap dolu iken defter uzunlugu: 0
bitis sirasi: obekteki-tekil, liste-1, liste-2, liste-3
```

Kapsam kapanırken bağlamalar en son bağlanandan başlayarak biter: `_obekteki`, `liste`den
sonra bağlandığı için ilk biten o oluyor. Ardından `liste` bitiyor, ama listenin kendi
içindeki üç `Iz` değeri **ekledikleri sırayla** bitiyor. Bağlamaların bitiş sırası ile bir
kabın içindeki elemanların bitiş sırası aynı kural değildir — biri bildirimin tersini,
öbürü ekleme sırasını izler; `Box` tek elemanlı bir kap olduğu için bu ikinci kural onda
görünmez, yalnızca birinci kural işler.

#### Öbekte Durmak Kullanım Biçimini Değiştirmez

Bir değerin öbekte durması, o değere nasıl erişildiğini değiştirmiyor. Bir `Box` içindeki
yapının alanlarına ve yöntemlerine, sanki değer doğrudan orada duruyormuş gibi erişilir;
aradaki kabı açmak için ayrı bir adım yazılmaz.

```rust
// kutu_erisimi.rs — box uzerinden erisim, deger dogrudan oradaymis gibi calisir
struct Nokta {
    x: i32,
    y: i32,
}

fn main() {
    let nokta = Box::new(Nokta { x: 3, y: 4 });
    println!("x: {}, y: {}", nokta.x, nokta.y);
    let toplam = nokta.x + nokta.y;
    println!("toplam: {}", toplam);
}
```

```
x: 3, y: 4
toplam: 7
```

`nokta.x` ve `nokta.y` satırları, `nokta`nın tipi `Nokta` olsaydı da `Box<Nokta>` olsaydı
da aynı yazılır. Aşağıdaki koşum bunu doğrudan karşılaştırıyor: aynı `Nokta` değeri önce
öbeğe alınmadan, sonra öbeğe alınarak okunuyor.

```rust
// erisim_karsilastirmasi.rs — box'lu ve box'suz erisim ayni satirla yaziliyor
struct Nokta {
    x: i32,
    y: i32,
}

fn main() {
    let dogrudan = Nokta { x: 1, y: 2 };
    let obekteki = Box::new(Nokta { x: 1, y: 2 });
    println!("dogrudan: x={}, y={}", dogrudan.x, dogrudan.y);
    println!("obekteki: x={}, y={}", obekteki.x, obekteki.y);
}
```

```
dogrudan: x=1, y=2
obekteki: x=1, y=2
```

İki satır arasındaki tek fark değerin nasıl kurulduğu (`Nokta { ... }` ile
`Box::new(Nokta { ... })`); alan okuma satırları birbirinin aynısı. Öbekte durmak
yalnızca değerin **nerede** tutulduğunu belirler; değerin okunma ve kullanılma biçimini
değiştirmez. Bu, ilerleyen derslerde paylaşımlı kapların da sürdüreceği bir düzendir: kabın
türü ne olursa olsun, içindeki değere erişim hep aynı satırla yazılır.

#### Öbeğe Almak Sahipliği Çoğaltmaz

Sahiplik ve Taşıma dersi, işleve taşınan, iç kapsama taşınan ve bir yapının alanına
taşınan değerin bitiş noktasını taşıdığını ama sayısını hiç değiştirmediğini ölçmüştü.
Aynı ilke, öbekteki bir değer için de geçerlidir: bir `Box` değeri kaç kez el
değiştirirse değiştirsin, taşıdığı `Iz` yalnızca **bir kez** biter.

Aşağıdaki koşum, tek bir `Box<Iz>` değerini iki ayrı işlev çağrısından geçiriyor ve son
sahibin elinde bırakıyor.

**PS2.** — "üç el değiştirmeden sonra bile tek bir bitiş kaydının oluştuğu" iddiası,
aşağıdaki koşumun `toplam kayit sayisi: 1` satırıyla doğrulanıyor.

```rust
// kutu_tasima.rs — box'a alinan bir degerin tasinmasi tek sahiplik sayisini degistirmiyor
use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz {
            ad: ad.to_string(),
            defter: Rc::clone(defter),
        }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

fn baska_kapsama(alinan: Box<Iz>) -> Box<Iz> {
    // Sahiplik burada devraliniyor ve ayni deger geri donduruluyor.
    alinan
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    {
        let ilk = Box::new(Iz::yeni("tek-sahip", &defter));
        let ikinci = baska_kapsama(ilk);
        let ucuncu = baska_kapsama(ikinci);
        println!("uc tasimadan sonra defter uzunlugu: {}", defter.borrow().len());
        println!("son sahip: {}", ucuncu.ad);
    }
    let kayit = defter.borrow();
    println!("toplam kayit sayisi: {}", kayit.len());
    println!("kayitlar: {}", kayit.join(", "));
}
```

```
uc tasimadan sonra defter uzunlugu: 0
son sahip: tek-sahip
toplam kayit sayisi: 1
kayitlar: tek-sahip
```

`ilk` adlı bağlama `baska_kapsama` işlevine taşınıyor, oradan `ikinci` adıyla geri
dönüyor, sonra yeniden aynı işleve taşınıp `ucuncu` adıyla dönüyor. Üç bağlama, üç ayrı
addır, ama hepsi aynı `Iz` değerinin farklı zamanlardaki tek sahibidir. `ucuncu` biterken
defter uzunluğunun sıfır olması, önceki iki taşımanın **hiçbirinin** bir bitiş
üretmediğini gösteriyor: yalnızca son sahibin kapsamı kapandığında bir kayıt açılıyor.
Defterde tek bir `tek-sahip` kaydı oluşması, öbeğe almanın sahiplik sayısını
**çoğaltmadığını** doğruluyor — taşıma yalnızca kimin sahip olduğunu güncelliyor, yeni bir
kayıt açmıyor.

Bu sonuç ilk bakışta beklenmedik gelmeyebilir, ama karşıt durumu düşünmek farkı netleştirir:
sahiplik çoğalsaydı, `baska_kapsama` her çağrıldığında defterde ayrı bir bitiş kaydı
oluşurdu ve toplam üç kayıt görülürdü. Sahiplik ve Taşıma dersinde yığıttaki bir değer için
kurulan "tek sahip" kuralı, değer öbeğe taşındığında da bozulmuyor; taşınan şey değerin
kendisi değil, yalnızca o değere sahip olma hakkıdır.

#### Box da Açık Çağrıyla Erken Bitebilir

Öbekteki bir değer, her zaman kabının kapanmasını beklemek zorunda değildir. Ödünç Alma
dersinde açık bir `drop` çağrısının bir değerin ömrünü erken bitirdiği ölçülmüştü; aynı
çağrı bir `Box` üzerinde de çalışır. Bu, "kabıyla birlikte" ile "açık çağrıda" sınıfları
arasındaki farkın **tipten değil**, değerin nasıl bitirildiğinden geldiğini gösteriyor.

**PS3.** — "erken bırakılan değerin, kapsamda kalan değerden önce bittiği" iddiası,
aşağıdaki koşumun `bitis sirasi` satırıyla doğrulanıyor.

```rust
// erken_birakma.rs — bir box degeri acik cagriyla erkenden birakilabilir
use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz {
            ad: ad.to_string(),
            defter: Rc::clone(defter),
        }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    {
        let erken = Box::new(Iz::yeni("erken-birakilan", &defter));
        let kalan = Box::new(Iz::yeni("kapsamda-kalan", &defter));
        drop(erken);
        println!("acik cagridan sonra defter uzunlugu: {}", defter.borrow().len());
        println!("kalan hala okunabilir: {}", kalan.ad);
    }
    let kayit = defter.borrow();
    println!("bitis sirasi: {}", kayit.join(", "));
}
```

```
acik cagridan sonra defter uzunlugu: 1
kalan hala okunabilir: kapsamda-kalan
bitis sirasi: erken-birakilan, kapsamda-kalan
```

`erken` değeri, `kalan`dan önce bağlanmasına rağmen kapsam sonunu beklemeden bitiyor;
`kalan` ise sıradan kapsam sonu kuralına uyuyor. Aynı tip — `Box<Iz>` — iki farklı bitiş
sınıfına düşebiliyor; sınıfı belirleyen kabın türü değil, kaynakta o değere ne
yapıldığıdır.

Bu dersin üç ölçümü bir araya geldiğinde, bir `Box` değerinin kursun açılışında kurulan
dört sınıftan üçüne girebildiği görülüyor: kapsamı doğal biçimde kapanırsa kabıyla
birlikte biter (Kap da Bir Sınıf bölümü), bir işleve ya da başka bir bağlamaya taşınırsa
bitiş noktası da onunla taşınır (Öbeğe Almak bölümü), açık bir çağrıyla bırakılırsa açık
çağrıda biter (bu bölüm). Yalnız kapsam sonu sınıfına giremez, çünkü öbekteki bir değer
her zaman ya bir kabın içindedir ya da bir taşımanın konusudur — hiçbir zaman yığıttaki
sıradan bir bağlama gibi kendi başına durmaz.

#### Özyinelemeli Bir Tip: Öbeğin Açtığı Kapı

M01/K03 Veri Yapıları dersi, bağlı liste ve ağaç gibi kendine referans veren yapıları
kavram olarak kurdu; bu ders o yapıyı yeniden öğretmiyor, yalnızca öbekte tekil
sahipliğin böyle bir tipi **mümkün kıldığını** ölçüyor.

Bir zincirin her halkasının kendi türünden bir sonraki halkayı doğrudan — bir kap
olmadan — taşıdığı bir tanım derleyici tarafından reddediliyor: her halka bir sonrakini
doğrudan içerdiğinde, tipin kendisinin ne kadar yer kaplayacağı hiçbir zaman belirlenmiş
sayılmıyor, çünkü halka sayısı kaynaktan sabit bir sınırla okunamıyor. Bu, bir işlevin
kendini çağırmasından farklı bir sorundur: işlev özyinelemesi çalışma zamanında adım adım
ilerler, ama bir tipin tanımı derleme zamanında tek seferde okunmak zorundadır — kendi
içinde sonsuza kadar açılan bir tanım bu okumayı bitiremez.

Kuralın en yalın hâli şöyle özetlenebilir: bir `Kayit` yapısının `sonraki` adlı alanına
doğrudan `Kayit` tipini yazan bir tanım hiçbir zaman kabul edilmez, çünkü `sonraki` yine
bir `Kayit`tir ve bu tanım kendi içinde asla kapanmaz. Aynı alana `Box<Kayit>` yazan bir
tanım kabul edilir, çünkü `Box` öbekte duran, kendisi sabit biçimli ayrı bir kaptır —
tanımın kendisi `Kayit`in içine doğrudan bir `Kayit` değil, sabit biçimli bir kabın
kendisini yerleştirir. Kabul edilen yazım, sonraki halkayı da tam olarak bu yolla taşıyor:
doğrudan değil bir `Box` üzerinden ve bu yüzden zincir istediği uzunlukta sürebiliyor.

**PS4.** — "zincirin bitiş sırasının kurulma sırasıyla aynı ilerlediği" iddiası, aşağıdaki
koşumun `bitis sirasi: halka-a, halka-b, halka-c` satırıyla doğrulanıyor — sıra,
bağlamaların bitişinde görülen tersine dönüşü izlemiyor.

```rust
// zincir.rs — box'un actigi kapi: kendini icinde barindiran bir tip
use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz {
            ad: ad.to_string(),
            defter: Rc::clone(defter),
        }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

enum Zincir {
    Bos,
    Dugum(Iz, Box<Zincir>),
}

fn uzunluk(z: &Zincir) -> usize {
    match z {
        Zincir::Bos => 0,
        Zincir::Dugum(iz, sonraki) => {
            println!("gezilen halka: {}", iz.ad);
            1 + uzunluk(sonraki)
        }
    }
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    {
        let zincir = Zincir::Dugum(
            Iz::yeni("halka-a", &defter),
            Box::new(Zincir::Dugum(
                Iz::yeni("halka-b", &defter),
                Box::new(Zincir::Dugum(
                    Iz::yeni("halka-c", &defter),
                    Box::new(Zincir::Bos),
                )),
            )),
        );
        println!("zincir uzunlugu: {}", uzunluk(&zincir));
    }
    let kayit = defter.borrow();
    println!("bitis sirasi: {}", kayit.join(", "));
}
```

```
gezilen halka: halka-a
gezilen halka: halka-b
gezilen halka: halka-c
zincir uzunlugu: 3
bitis sirasi: halka-a, halka-b, halka-c
```

Bu sıra ilk bakışta şaşırtıcı görünebilir, çünkü bu derste önce ölçülen kural bağlamaların
son bağlanandan başlayarak bittiğiydi. Ama burada tek bir dış bağlama var — `zincir` —, üç
ayrı bağlama yok. `zincir` bittiğinde önce kendi `Iz` alanı biter (`halka-a`), ardından
kendi `Box<Zincir>` alanı biter; o `Box` da kendi içindeki değeri bitirirken önce onun
`Iz` alanını bitiriyor (`halka-b`), sonra kendi `Box`unu ve bu böyle sürüyor. Bitiş,
dıştan içe doğru ilerleyen tek bir zincirleme çağrı olduğu için kurulma sırasıyla aynı
yönde ilerliyor; bu, "Kap da Bir Sınıf" bölümündeki liste örneğinden farklı bir bitiş
biçimidir — orada çok sayıda bağımsız bağlama vardı, burada iç içe geçmiş tek bir bağlama
zinciri var.

Dört ölçüm bir araya geldiğinde tek bir resim çıkıyor: `Box`, bir değerin **nerede**
durduğunu değiştiren ama **kaç sahibi olduğunu** hiç değiştirmeyen bir kaptır. Değere
erişim biçimi aynı kalıyor, taşıma bitiş noktasını taşıyor ama sayıyı çoğaltmıyor, açık
bir çağrı erken bitirebiliyor ve bu tekil sahiplik sayesinde bir tip kendi türünden bir
sonraki halkayı taşıyabiliyor. Sıradaki sorunun zemini de tam burada kuruluyor: bu dört
ölçümün hiçbirinde sahiplik sayısı birden fazla olmadı — hep tek bir bağlama, tek bir
anda, o değerin sahibiydi.

#### Özet

- Bir değer öbekte durduğunda da tek bir sahibi olur; `Box` bu sayıyı değiştirmez.
- Bir kabın içindeki tekil değer ile listedeki değerler farklı bitiş sırası kurallarına
  uyar: biri bildirimin tersini, öbürü ekleme sırasını izler.
- Öbekte durmak bir değerin okunma ve kullanılma biçimini değiştirmez.
- Öbekteki bir değer taşınsa bile defterde yalnızca tek bir bitiş kaydı oluşur.
- Aynı tip, kaynakta yapılana göre "kabıyla birlikte" ya da "açık çağrıda" sınıflarından
  birine düşebilir.
- Öbekte tekil sahiplik, kendine referans veren bir tipin derlenebilmesini sağlar; bir
  zincir tipinin bitiş sırası bu durumda kurulma sırasıyla aynı yönde ilerleyebilir.

#### Sonraki Adım

Bu derste öbekteki bir değer taşınsa da, erken bırakılsa da, zincirlense de, sahibi hep
tek kaldı. Sıradaki ders bu varsayımı kaldırıyor: aynı değeri aynı anda birden çok
bağlamanın sahiplenebildiği bir düzenek — ve bu paylaşımın kaynaktan okunabilir bir
sayaçla nasıl izlendiği ölçülüyor.

### Referans Sayımı

Source: https://academia.sh/tr/kurslar/sahiplik/referans-sayimi

Bir Rc değerinin sayacının her kopyada arttığı, her bitişte azaldığı ve değerin ancak sayaç sıfıra inince deftere düştüğü ölçülüyor; bir referans almanın bu sayacı hiç değiştirmediği ve hangi kopyanın bırakıldığının değil kaç kopyanın kaldığının belirleyici olduğu gösteriliyor.

Önceki ders, öbekteki bir değerin taşınsa da, erken bırakılsa da, zincirlense de hep tek bir
sahibi olduğunu ölçtü. Bu dersin sorusu tam o varsayımı kaldırıyor: bir değerin sahibi birden
çok olabilir mi? Yanıt evet — ama bu evet bir kaçamak değil, kaynaktan okunabilen bir sayaçla
izlenen, belirlenimci bir paylaşımdır. Sayacın izlediği şey bir değerin bitiş noktasıdır;
Eşzamanlılık kursunun (M09/K03) ölçtüğü koşan bir birimin durması bu kursun sorusu değil.

`Rc<T>`, bir değeri öbeğe koyup kaç bağlamanın o değere ortak eriştiğini sayan bir kaptır.
Değer, bu sayaç sıfıra düşünceye kadar yaşar; sayaç sıfıra indiği an, önceki derste görülen
tekil sahiplik biter ve değer defterine düşer. Bu ders o sayacı doğrudan okuyarak, her
kopyalamada ve her bitişte ne olduğunu, hangi bağlamanın "sahip" sayıldığını ve hangisinin
sayılmadığını ölçüyor.

#### Neden Bir Referans Yetmez

Ödünç Alma dersi, bir referansın ödünç aldığı değerden daha uzun yaşayamayacağını
ölçmüştü; Yaşam Süresi Kavramı dersi bu sınırı bir geçerlilik aralığı olarak adlandırdı.
Bu sınır, aynı değere birden çok yerden erişmek isteyen ama kaynaktaki tek sahiplik
bağlamasının ömrüyle sınırlı kalmak istemeyen bir kullanım için yetersiz kalır: referans,
sahibinin kapsamı kapanınca geçersiz olur, kaç yerden okunursa okunsun — sahibinin kendisi
hâlâ tektir. `Rc`, bu sınırı bir kopyanın kendisini de bir sahip yaparak aşıyor: artık
ödünç alan bir taraf değil, kendi başına bir sahip olan bir kopya söz konusu ve bu kopya
orijinal bağlamadan bağımsız olarak kendi kapsamının sonuna kadar yaşayabiliyor.

#### Sahiplik Sayılabilir Hâle Geliyor

Bir değer `Rc::new` ile öbeğe konduğunda sayaç bire kurulur. `Rc::clone` çağrıldığında yeni
bir kopya üretilir, sayaç bir artar; kopyalardan biri bittiğinde sayaç bir azalır. Bu
kopyalar birbirinin **aynı** değerine erişir — her biri kendi ayrı bir değer taşımaz,
hepsi tek bir `Iz`yi paylaşır.

**PS5.** — "sayacın her kopyada arttığı ve her bitişte azaldığı" iddiası, aşağıdaki koşumun
`1, 2, 3, 2` sırasıyla basılan sayaç değerleriyle doğrulanıyor.

```rust
// referans_sayaci.rs — Rc'nin sayaci her kopyada artiyor, her bitiste azaliyor
use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz {
            ad: ad.to_string(),
            defter: Rc::clone(defter),
        }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    {
        let paylasilan: Rc<Iz> = Rc::new(Iz::yeni("paylasilan", &defter));
        println!("kurulunca sayac: {}", Rc::strong_count(&paylasilan));

        let ikinci = Rc::clone(&paylasilan);
        println!("bir kopyadan sonra sayac: {}", Rc::strong_count(&paylasilan));

        {
            let _ucuncu = Rc::clone(&paylasilan);
            println!("iki kopyadan sonra sayac: {}", Rc::strong_count(&paylasilan));
            println!("ic kapsam biterken defter uzunlugu: {}", defter.borrow().len());
        }
        println!("ic kapsam bittikten sonra sayac: {}", Rc::strong_count(&paylasilan));
        println!("ikinci kopya hala okunabilir: {}", ikinci.ad);
    }
    let kayit = defter.borrow();
    println!("defterdeki kayit sayisi: {}", kayit.len());
    println!("kayitlar: {}", kayit.join(", "));
}
```

```
kurulunca sayac: 1
bir kopyadan sonra sayac: 2
iki kopyadan sonra sayac: 3
ic kapsam biterken defter uzunlugu: 0
ic kapsam bittikten sonra sayac: 2
ikinci kopya hala okunabilir: paylasilan
defterdeki kayit sayisi: 1
kayitlar: paylasilan
```

İç kapsam kapanırken `_ucuncu` bitiyor, ama defter uzunluğu sıfır kalıyor: `_ucuncu`nun
bitişi yalnızca sayacı ikiye indiriyor, `Iz` değerinin kendisini bitirmiyor. `paylasilan`
ve `ikinci` hâlâ aynı değere erişebiliyor — `ikinci.ad` okunduğunda hâlâ `paylasilan`
metnini veriyor, çünkü ikisi aynı değeri paylaşıyor. Dış kapsam kapandığında geri kalan iki
kopya da bitiyor, sayaç sıfıra iniyor ve ancak o an defterde tek bir kayıt beliriyor.
Üç kopyaya rağmen defterde tek kayıt olması, paylaşımın değeri **çoğaltmadığını**, yalnızca
ona erişen yol sayısını çoğalttığını gösteriyor.

#### Kopyalamak Veri Kopyalamak Değildir

Yukarıdaki koşumda `Iz::yeni` yalnızca **bir kez** çağrılıyor — `paylasilan` kurulurken.
`ikinci` ve `_ucuncu`, `Rc::clone(&paylasilan)` ile üretiliyor; bu çağrı ne `Iz::yeni`yi
yeniden çalıştırıyor ne de `ad` alanını yeniden kuruyor. `ikinci.ad`in hâlâ `paylasilan`
metnini vermesi bir rastlantı değil: `ikinci` ayrı bir `Iz` değeri taşımıyor, `paylasilan`
ile **aynı** değere bakan ikinci bir erişim yolu taşıyor. Bu, bir dizginin ya da bir
listenin `.clone()` çağrısından farklıdır — onlarda içerik gerçekten kopyalanır ve
sonradan biri değiştirilse öbürü değişmez. `Rc::clone`, adındaki fiile rağmen, taşıdığı
değeri değil yalnızca sayacı ve erişimi çoğaltıyor. Bu fark, ilerleyen bir derste
paylaşılan verinin **değiştirilmesi** gündeme geldiğinde önemli sonuçlar doğuruyor: iki
kopyadan biri üzerinden yapılan bir değişiklik, öbür kopyadan da görülebilir hâle gelir,
çünkü aslında değişen tek bir değerdir.

#### Her Değerin Kendi Sayacı Vardır

Bir programda birden çok paylaşılan değer varsa, her birinin sayacı ayrıdır. Bir değerin
kopyalanması ya da bitmesi, başka bir değerin sayacına dokunmaz.

```rust
// bagimsiz_sayaclar.rs — farkli degerlerin sayaclari birbirinden bagimsizdir
use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz {
            ad: ad.to_string(),
            defter: Rc::clone(defter),
        }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    let birinci: Rc<Iz> = Rc::new(Iz::yeni("birinci-deger", &defter));
    let ikinci: Rc<Iz> = Rc::new(Iz::yeni("ikinci-deger", &defter));

    let birinci_kopya = Rc::clone(&birinci);
    println!("birinci sayac: {}", Rc::strong_count(&birinci));
    println!("ikinci sayac: {}", Rc::strong_count(&ikinci));

    drop(birinci_kopya);
    drop(birinci);
    println!("defter (yalniz birinci bitti): {}", defter.borrow().join(", "));

    drop(ikinci);
    println!("defter (ikisi de bitti): {}", defter.borrow().join(", "));
}
```

```
birinci sayac: 2
ikinci sayac: 1
defter (yalniz birinci bitti): birinci-deger
defter (ikisi de bitti): birinci-deger, ikinci-deger
```

`birinci` bir kez kopyalandığı için sayacı iki, `ikinci` hiç kopyalanmadığı için sayacı
bir. `birinci`nin iki kopyası da bittiğinde `ikinci`nin sayacı hâlâ bir olarak kalıyor —
`ikinci` bu değişiklikten habersiz. Aynı `defter` her iki değer için de ortak kullanılıyor
(bu bir kayıt aracı, sayılan değerin kendisi değil), ama her `Iz`nin kendi `Rc` sarmalayıcısı
kendi sayacını tutuyor. Bir programda kaç ayrı paylaşılan değer varsa, o kadar ayrı ve
birbirinden bağımsız sayaç vardır.

#### Paylaşım Sahiplik Kuralını İhlal Etmiyor, Genelliyor

Önceki derste kurulan "tek sahip" kuralı burada bozulmuyor, genelleniyor: sahip artık tek
bir bağlama değil, sayaç sıfıra düşene kadar aktif kalan kopyaların **kümesidir**. Sayaç
sıfıra indiği an kesin olarak bellidir ve bu an, koşumda her zaman aynı sırayla üretilen
bir kayıttır — bir sonraki adımın ne yapacağına bağlı bir tahmin değil, kaynaktaki kopya
sayısının doğrudan sonucudur. Bu, tek iş parçacığında çalışan sıradan bir tam sayı gibi
davranır: `Rc::clone` çağrısı bir kopya üretip sayacı artırıyor, kopyanın bitişi sayacı
azaltıyor ve iki işlem de aynı yerden — aynı kapsamdan — yürüyor.

Sayaç, tek tek adlandırılmış bağlamalarla sınırlı değildir; bir döngüde üretilen kopyalar
da aynı kurala uyar. Aşağıdaki koşum beş kopyayı bir listeye topluyor, sonra listeyi tek
seferde boşaltıyor.

```rust
// toplu_kopyalama.rs — bir donguyle uretilen kopyalar temizlenince sayac baslangica doner
use std::rc::Rc;

fn main() {
    let paylasilan: Rc<i32> = Rc::new(7);
    let mut kopyalar: Vec<Rc<i32>> = Vec::new();
    for _ in 0..5 {
        kopyalar.push(Rc::clone(&paylasilan));
    }
    println!("bes kopyadan sonra sayac: {}", Rc::strong_count(&paylasilan));

    kopyalar.clear();
    println!("kopyalar temizlenince sayac: {}", Rc::strong_count(&paylasilan));
}
```

```
bes kopyadan sonra sayac: 6
kopyalar temizlenince sayac: 1
```

Beş kopya listeye eklenince sayaç altıya çıkıyor — ilk kurulan `paylasilan` da bir kopya
sayılıyor. Liste tek seferde boşaltıldığında beş kopya art arda bitiyor ve sayaç bire
dönüyor; `paylasilan` kendisi hâlâ elde olduğu için değer henüz bitmiyor. Bu örnek `Iz`
düzeneğini kullanmıyor, çünkü burada ölçülen şey bir bitiş kaydı değil, sayacın kendisinin
toplu işlemler altında da aynı kuralı izlediği.

#### Sayılan Şey Sahiptir, Ödünç Değil

Sayaç, yalnızca `Rc::clone` çağrılarını sayar. Paylaşılan değere bir **referans** almak —
onu okumak için ödünç almak — sayacı hiç değiştirmez, çünkü ödünç alan taraf değerin
sahibi değildir, yalnızca ona geçici olarak erişir.

**PS6.** — "bir referans almanın sayacı değiştirmediği" iddiası, aşağıdaki koşumda
`kurulunca sayac` ile `odunc alip okuduktan sonra sayac` satırlarının aynı değeri
(`1`) vermesiyle doğrulanıyor.

```rust
// odunc_sayaca_girmez.rs — bir referans almak Rc sayacini degistirmiyor
use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz {
            ad: ad.to_string(),
            defter: Rc::clone(defter),
        }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

fn oku(deger: &Iz) -> usize {
    deger.ad.len()
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    let paylasilan: Rc<Iz> = Rc::new(Iz::yeni("olcum-degeri", &defter));
    println!("kurulunca sayac: {}", Rc::strong_count(&paylasilan));

    let uzunluk = oku(&paylasilan);
    println!(
        "odunc alip okuduktan sonra sayac: {} (uzunluk {})",
        Rc::strong_count(&paylasilan),
        uzunluk
    );

    let kopya = Rc::clone(&paylasilan);
    println!("kopyaladiktan sonra sayac: {}", Rc::strong_count(&paylasilan));

    drop(kopya);
    println!("kopyayi birakinca sayac: {}", Rc::strong_count(&paylasilan));
}
```

```
kurulunca sayac: 1
odunc alip okuduktan sonra sayac: 1 (uzunluk 12)
kopyaladiktan sonra sayac: 2
kopyayi birakinca sayac: 1
```

`oku` işlevi `&Iz` alıyor, `Rc<Iz>`nin kendisini değil — bu yüzden çağrı sayacı hiç
etkilemiyor. Sayaç yalnızca `Rc::clone` çağrısıyla ikiye çıkıyor ve kopya açıkça
bırakıldığında yeniden bire dönüyor. Ödünç Alma dersinde kurulan "ödünç alınan değer
bitmiyor" ilkesi burada da geçerli: bir referans, değerin sahiplik defterine hiç
girmiyor; yalnızca kopyalar sahip sayılıyor, ödünç alanlar sayılmıyor.

Bu ayrım küçük görünse de yanlış anlaşılmaya açıktır, çünkü `Rc<Iz>` üzerinden bir
işleve `&paylasilan` geçirmek ile `Rc::clone(&paylasilan)` geçirmek yüzeysel olarak
benzer görünür — ikisi de bir `&` işareti taşıyabilir. Aradaki fark şudur: `oku(&paylasilan)`
çağrısı `Rc<Iz>`yi ödünç alıp içindeki `&Iz`ye otomatik olarak iniyor, hiçbir yeni sahip
kurmuyor; `Rc::clone(&paylasilan)` ise açıkça yeni bir sahip kopyası üretiyor. Kod
okunurken bu iki niyeti ayırt etmenin yolu, çağrının `clone` adını taşıyıp taşımadığına
bakmaktır — sayaç yalnızca o adı taşıyan çağrıya tepki verir.

#### Sıra Değil, Sayı Belirleyici

Önceki derste bir kabın içindekilerin bitiş **sırası** ölçülmüştü — hangi değerin önce,
hangisinin sonra bittiği belirleyiciydi. Referans sayımında durum farklıdır: hangi
kopyanın hangi sırayla bırakıldığı değeri bitirmez, yalnızca **kaç** kopyanın kaldığı
belirler.

**PS7.** — "değerin, hangi kopyanın değil son kalan kopyanın bırakılmasıyla bittiği"
iddiası, aşağıdaki koşumda dört kopyadan ilk kurulanın ortadan bırakılmasına rağmen
defterin boş kalmasıyla, yalnızca son kopya giderken dolmasıyla doğrulanıyor.

```rust
// sira_onemsiz.rs — Rc'de hangi kopyanin birakildigi degil, kac kopya kaldigi belirleyici
use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz {
            ad: ad.to_string(),
            defter: Rc::clone(defter),
        }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    let paylasilan: Rc<Iz> = Rc::new(Iz::yeni("son-kopya-birakilinca-biten", &defter));
    let a = Rc::clone(&paylasilan);
    let b = Rc::clone(&paylasilan);
    let c = Rc::clone(&paylasilan);
    println!("dort kopyadan sonra sayac: {}", Rc::strong_count(&a));

    drop(b);
    println!("ortadaki kopya birakilinca sayac: {}", Rc::strong_count(&a));
    println!("defter hala bos mu: {}", defter.borrow().is_empty());

    drop(paylasilan);
    println!("ilk kurulan kopya birakilinca sayac: {}", Rc::strong_count(&a));
    println!("defter hala bos mu: {}", defter.borrow().is_empty());

    drop(a);
    drop(c);
    let kayit = defter.borrow();
    println!("son kopya da birakilinca kayit: {}", kayit.join(", "));
}
```

```
dort kopyadan sonra sayac: 4
ortadaki kopya birakilinca sayac: 3
defter hala bos mu: true
ilk kurulan kopya birakilinca sayac: 2
defter hala bos mu: true
son kopya da birakilinca kayit: son-kopya-birakilinca-biten
```

Dört kopyadan `b` bırakılıyor, sonra ilk kurulan `paylasilan` bırakılıyor — kuruluş
sırasına göre ne ilk ne son olan bir kopya, sonra da en eski kopyanın kendisi gidiyor. İki
bırakmadan sonra bile defter boş kalıyor, çünkü geriye hâlâ iki kopya (`a` ve `c`) var.
Değer ancak bu ikisi de bırakıldığında biter. Bir önceki derste bir kabın içindekilerin
bitişi **hangi sırayla** eklendiğine bağlıydı; burada bitiş yalnızca **kaç** kopyanın
kaldığına bağlı — hangi kopyanın adı, hangi sırayla bırakıldığı sonucu değiştirmiyor. Bu
fark, iki kap türü arasındaki temel ayrımı özetliyor: bir liste ya da bir `Box`, tek bir
sahiplik zincirinin **konumunu** kaydeder ve bu yüzden sıraya duyarlıdır; bir `Rc`,
sahiplik zincirinin **uzunluğunu** kaydeder ve bu yüzden yalnızca sayıya duyarlıdır.

Yukarıdaki koşumlarda kullanılan açık `drop` çağrısı, Öbekte Tekil Sahiplik dersinde
görülen açık çağrı fikrini burada da sürdürüyor, ama sonucu farklıdır. Orada bir `Box`
üzerinde açık çağrı değerin kendisini erkenden bitiriyordu — tek sahip olduğu için başka
seçenek yoktu. Burada aynı çağrı yalnızca **bir kopyayı** bırakıyor; değerin kendisi,
geriye başka kopya kaldığı sürece bitmiyor. Aynı `drop` işlevi, tek sahiplikte kesin bir
bitiş, paylaşımlı sahiplikte ise koşullu bir azaltma anlamına geliyor — anlam, çağrıldığı
değerin sahiplik biçimine göre değişiyor.

Dört koşum bir araya geldiğinde, referans sayımının sahiplik kuralını nasıl genellediği
netleşiyor. Sayaç her zaman tek bir yerden, tek bir sırayla güncelleniyor; kopyalamak
veriyi değil erişimi çoğaltıyor; bir referans hiçbir zaman bu sayıma girmiyor; ve
bitişi belirleyen şey kopyaların kimliği değil miktarıdır. Bu dört özellik birlikte, hâlâ
belirlenimci ve kaynaktan okunabilir bir bitiş noktası sağlıyor — sayaç sıfıra indiği an,
tıpkı önceki derste tek sahipli bir değerin kapsam sonu gibi, koşumda kesin ve tekrarlanır
biçimde görülüyor.

#### Özet

- `Rc<T>`, bir değeri öbeğe koyup ona erişen kopya sayısını sayan bir kaptır.
- Sayaç her `Rc::clone` çağrısında artar, her kopyanın bitişinde azalır.
- Değer, ancak sayaç sıfıra indiğinde defterine düşer — ömrü **kabıyla birlikte**, son
  kalan kopyanın bitişinde biter; bu an kaynaktan okunabilir ve
  koşumda her zaman aynı sırayla üretilir.
- Bir referans almak sayacı değiştirmez; yalnızca kopyalamak değiştirir.
- Değerin bitişi hangi kopyanın bırakıldığına değil, kaç kopyanın kaldığına bağlıdır.
- `Rc::clone` taşınan değeri değil, sayacı ve erişimi çoğaltır; kopyalar aynı değere bakar.

#### Sonraki Adım

Bu derste ölçülen sayaç, tek bir bağlamda, sıradan bir tam sayı gibi güncellendi: her
kopyalama ve her bitiş aynı kapsamdan, aynı sırayla yürüdü. Sıradaki ders aynı sayma
işini yapan ama sayacın kendisini farklı bir biçimde güncelleyen bir türü ölçüyor — davranış
aynı kalıyor, yalnızca sayacın güncellenme biçimi değişiyor; hangi bağlamda bu farkın
gerektiği, bu dersin kapsamının dışında kalıyor.

### Atomik Referans Sayımı

Source: https://academia.sh/tr/kurslar/sahiplik/atomik-referans-sayimi

Aynı sayma düzeneğinin Arc ile kurulduğunda da birebir aynı bitiş kaydını ürettiği, farkın davranışta değil sayacın nasıl güncellendiğinde olduğu ölçülüyor; hangi bağlamda kullanılabildiği K04'ün konusu olduğu için burada anlatılmıyor. Paylaşılan verinin Arc üzerinden yalnızca okunabildiği, doğrudan değiştirilemediği ayrıca gösteriliyor.

Önceki ders, referans sayımının tek bir bağlamda, sıradan bir tam sayı gibi güncellenen bir
sayaçla çalıştığını, bu sayacın her kopyalamada arttığını ve her bitişte azaldığını ölçtü. Bu
ders aynı sayma işini yapan, ama sayacın kendisini farklı bir biçimde güncelleyen bir türü
ölçüyor: `Arc<T>`. Baştan söylenmesi gereken bir sınır var: bu farkın **hangi bağlamda**
gerekli olduğu — birden çok iş parçacığının aynı değere aynı anda erişmesi — bu dersin konusu
değil, M10/K04'ün konusudur. Burada yalnız şu ölçülüyor: sayaç atomik biçimde güncellendiğinde
davranış değişiyor mu, değişmiyor mu? Ölçülen yine bir değerin bitişi; Eşzamanlılık kursunun
(M09/K03) sorduğu koşan bir birimin nasıl duracağı değil.

Bu sınırın kod üzerindeki karşılığı açıktır: bu derste hiçbir yerde bir iş parçacığı
başlatılmıyor. Aşağıdaki bütün koşumlar, önceki dersteki gibi, tek bir çalışma akışı
içinde baştan sona yürüyor. Bu bir eksiklik değil, bir sınır kararı — `Arc`in adı bir
kullanım bağlamını çağrıştırsa da, bu dersin ölçtüğü şey yalnızca sayacın kendisi,
kullanıldığı ortam değil. Bu, bu konunun daha önce de uyguladığı bir kurala uyuyor: Öbekte
Tekil Sahiplik dersinde bir yazımın neden reddedildiği düzyazıda tarif edilmiş, kabul
edilen yazım koşturulmuştu; burada da bir türün adının çağrıştırdığı bağlam anlatılmıyor,
yalnızca ölçülebilir olan — sayacın kendisi — koşturuluyor.

#### Aynı Sayaç, Farklı Güncelleme Biçimi

`Arc`, `Rc` ile aynı arayüzü taşır:

| Rc'deki karşılık | Arc'daki karşılık |
|---|---|
| `Rc::new` | `Arc::new` |
| `Rc::clone` | `Arc::clone` |
| `Rc::strong_count` | `Arc::strong_count` |

Her satırın solu ve sağı, aynı işi yapan iki farklı türün aynı adlı çağrısıdır: bir değeri
öbeğe koyup sayacı bire kurmak, bir kopya üretip sayacı artırmak, sayacın anlık değerini
okumak. Aradaki tek fark, artırma ve azaltma işleminin nasıl gerçekleştirildiğidir. Sıradan
bir artırma üç ayrı adımdan oluşur: mevcut değer okunur, bir eklenir, sonuç geri yazılır.
**Atomik (atomic)** bir artırma bu üç adımı, arada başka bir şeyin araya giremeyeceği tek
bir bölünmez işlem olarak gerçekleştirir. `Rc`nin sayacı sıradan artırma kullanır, `Arc`nin
sayacı atomik artırma kullanır — ama her ikisi de aynı matematiksel sonucu üretir: bir
kopyalamada bir artış, bir bitişte bir azalış. Aynı ayrım azaltma için de geçerlidir: bir
kopyanın bitmesi, sayacı sıradan ya da atomik bir azaltmayla bir indirir; hangi yöntem
kullanılırsa kullanılsın, sayacın son ulaştığı değer aynıdır.

Bu dersin ölçümü, önceki dersteki kurguyu birebir aynı biçimde `Arc` ile yeniden
koşturuyor.

Bu derste ve önceki derste kopya `paylasilan.clone()` değil `Rc::clone(&paylasilan)` ya
da `Arc::clone(&paylasilan)` biçiminde çağrılıyor. İkisi de aynı sonucu üretir — Rust bir
yöntem çağrısını hem `deger.clone()` hem `Tur::clone(&deger)` biçiminde yazmaya izin verir
— ama bu ders boyunca ikinci biçim tercih ediliyor, çünkü ilk biçim okuyana "içeriği
derinlemesine kopyalayan bir işlem" izlenimi verebilir. Oysa burada kopyalanan yalnızca
sayaç ve erişimdir; `Tur::clone(&deger)` yazımı bunu kaynakta daha açık kılıyor.

**PS8.** — "aynı kurgunun `Arc` ile de birebir aynı sayaç dizisini ürettiği" iddiası,
aşağıdaki koşumun `1, 2, 3, 2` sırasıyla basılan sayaç değerleriyle doğrulanıyor — bu,
önceki dersteki `Rc` koşumuyla tıpatıp aynı dizi.

```rust
// atomik_sayac.rs — Arc ayni sayma islemini atomik olarak yapiyor
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz {
            ad: ad.to_string(),
            defter: Rc::clone(defter),
        }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    {
        let paylasilan: Arc<Iz> = Arc::new(Iz::yeni("atomik-paylasilan", &defter));
        println!("kurulunca sayac: {}", Arc::strong_count(&paylasilan));

        let ikinci = Arc::clone(&paylasilan);
        println!("bir kopyadan sonra sayac: {}", Arc::strong_count(&paylasilan));

        {
            let _ucuncu = Arc::clone(&paylasilan);
            println!("iki kopyadan sonra sayac: {}", Arc::strong_count(&paylasilan));
        }
        println!("ic kapsam bittikten sonra sayac: {}", Arc::strong_count(&paylasilan));
        println!("ikinci kopya hala okunabilir: {}", ikinci.ad);
    }
    let kayit = defter.borrow();
    println!("defterdeki kayit sayisi: {}", kayit.len());
    println!("kayitlar: {}", kayit.join(", "));
}
```

```
kurulunca sayac: 1
bir kopyadan sonra sayac: 2
iki kopyadan sonra sayac: 3
ic kapsam bittikten sonra sayac: 2
ikinci kopya hala okunabilir: atomik-paylasilan
defterdeki kayit sayisi: 1
kayitlar: atomik-paylasilan
```

Bu koşumdaki `Rc::clone(defter)` çağrısı yalnızca notların tutulduğu `defter`i paylaşmak
için kullanılıyor; ölçülen paylaşım `paylasilan` üzerinde `Arc` ile kuruluyor. Sayaç
sırası — bir, iki, üç, sonra iki — önceki dersle birebir aynı. İç kapsam kapanınca `_ucuncu`
bitiyor, sayaç ikiye dönüyor, ama `Iz` değeri henüz bitmiyor; dış kapsam kapanınca geri kalan
iki kopya da bitiyor ve defterde tek bir kayıt beliriyor. `Arc`, `Rc`nin yaptığı her şeyi
aynı sırayla, aynı sonuçla yapıyor.

Son satırda `ikinci.ad` okunduğunda hâlâ `atomik-paylasilan` metnini veriyor — tıpkı bir
önceki derste `Rc::clone`nun yaptığı gibi, `Arc::clone` da `Iz::yeni`yi yeniden çağırmıyor,
yalnızca aynı değere ikinci bir erişim yolu açıyor. Kopyalamak Veri Kopyalamak Değildir
bölümünde kurulan ayrım burada da geçerli: `Arc::clone`, adındaki fiile rağmen veriyi değil
sayacı ve erişimi çoğaltıyor. Bu koşumda `Iz::yeni` de yalnızca bir kez çağrılıyor;
`ikinci` ve `_ucuncu`, `paylasilan` ile aynı öbek konumundaki aynı değere bakıyor.

#### Aynı Kurgu, Aynı Sonuç

İki dersin koşumları yan yana konduğunda fark görünmüyor: sayaç dizisi aynı, defter
uzunluğu aynı, kopyanın bitmesiyle sayacın azalması arasındaki ilişki aynı. Bu, rastlantı
değil — `Arc`, `Rc` ile aynı sözleşmeyi taşıyan bir türdür; ikisi de "sayaç sıfıra inince
değer biter" kuralını uyguluyor. Aralarındaki fark **davranışta değil**, sayacı güncelleyen
işlemin kendisinde: biri sıradan bir artırma/azaltma yapıyor, öbürü bunu atomik olarak
yapıyor. Bu farkın hangi bağlamda anlam kazandığı — birden çok iş parçacığının aynı sayaca
aynı anda erişmesi — burada ele alınmıyor; o soru M10/K04'ün konusu.

Referans Sayımı dersinde ölçülen iki başka özellik de — her değerin kendi sayacının
olması ve bitişin hangi kopyanın değil kaç kopyanın kaldığına bağlı olması — `Arc` için
ayrıca sınanabilir. Aşağıdaki koşum iki bağımsız `Arc` değeri kuruyor, birinin üç kopyasını
kuruluş sırasının dışında bir sırayla bırakıyor ve öbür değerin bundan etkilenmediğini
gösteriyor.

```rust
// arc_ozellikleri.rs — bagimsiz sayaclar ve sira-bagimsizligi Arc icin de gecerli
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz {
            ad: ad.to_string(),
            defter: Rc::clone(defter),
        }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    let birinci: Arc<Iz> = Arc::new(Iz::yeni("birinci-atomik", &defter));
    let ikinci: Arc<Iz> = Arc::new(Iz::yeni("ikinci-atomik", &defter));

    let a = Arc::clone(&birinci);
    let b = Arc::clone(&birinci);
    println!(
        "uc kopyadan sonra birinci sayac: {}, ikinci sayac: {}",
        Arc::strong_count(&birinci),
        Arc::strong_count(&ikinci)
    );

    drop(a);
    drop(birinci);
    println!(
        "iki kopya birakilinca defter (hala bos olmali): {}",
        defter.borrow().join(", ")
    );

    drop(b);
    println!(
        "son kopya da birakilinca defter: {}",
        defter.borrow().join(", ")
    );
    println!("ikinci sayac hala degismedi: {}", Arc::strong_count(&ikinci));

    drop(ikinci);
    let kayit = defter.borrow();
    println!("ikinci de birakilinca defter: {}", kayit.join(", "));
}
```

```
uc kopyadan sonra birinci sayac: 3, ikinci sayac: 1
iki kopya birakilinca defter (hala bos olmali): 
son kopya da birakilinca defter: birinci-atomik
ikinci sayac hala degismedi: 1
ikinci de birakilinca defter: birinci-atomik, ikinci-atomik
```

Üç kopyadan `a` ve orijinal `birinci` bağlaması bırakıldığında defter hâlâ boş — geriye
`b` kaldığı için `birinci-atomik` henüz bitmiyor. `b` da bırakılınca defter doluyor.
Bu sırada `ikinci`nin sayacı hiç değişmiyor: iki değer, iki bağımsız kayıt tutuyor.
Sonuç, Referans Sayımı dersinde `Rc` için görülenle birebir aynı — yalnızca sayacı
güncelleyen işlem farklı. Bırakma sırası burada da `a`, `birinci`, `b` biçiminde, kuruluş
sırasının (`birinci`, sonra `a`, sonra `b`) dışında seçildi; sonuç yine değişmedi, çünkü
belirleyici olan sıradaki kopyanın kimliği değil, geriye kaç kopya kaldığı.

#### İki Ayrı Tür, Görünür Bir Seçim

Rust'ın bunu tek bir yapılandırılabilir tür yerine iki ayrı tür — `Rc` ve `Arc` — olarak
sunması bir tasarım kararıdır. Sayacın hangi biçimde güncelleneceği bir çalışma zamanı
bayrağı ya da bir kurulum seçeneği değil, kaynak kodunda **görünür bir tip seçimidir**:
bir değeri `Rc::new` ile mi yoksa `Arc::new` ile mi kurduğunuz, o değeri kimin okuyup
kimin okuyamayacağını değil, sayacının hangi işlemle güncelleneceğini kaynaktan okunur
kılar. Bu, kursun daha önce defalarca gördüğü bir düzenin tekrarıdır: davranış farkı bir
çalışma zamanı kararına değil, bir tip farkına bağlanıyor. İki tür birbirinin yerini
büyük ölçüde tutabilir — aynı `new`, `clone`, `strong_count` çağrılarıyla çalışırlar —
ama hangisinin seçildiği, o değere dair kalıcı bir bilgi olarak kaynakta durur.

Bu düzen, Rust Temelleri kursunun Sıralı ve Küme Yapıları dersinde görülen ayrımla aynı
biçimdedir: karma sözlük ile sıralı sözlük de aynı temel işi görür, ama aralarındaki
seçim bir çalışma zamanı kararı değil, hangi tipin yazıldığına bağlı bir kaynak kararıdır.
`Rc` ile `Arc` arasındaki seçim de aynı kalıba uyuyor — iki tür de "kaç kopya var"
sorusuna aynı yanıtı veriyor, farklı olan yalnızca bu yanıtı üretme biçimi.

#### Atomik Sayaç Veriyi Değil Sayacı Korur

Atomik güncelleme yalnızca **sayacı** korur; sayaç değil de paylaşılan verinin kendisi söz
konusu olduğunda `Arc` hiçbir ek güvence vermez. Bir `Arc` üzerinden bir alana doğrudan
yazmaya çalışan bir satır derlenmiyor: `Arc`, tıpkı bir kopyalanmış `Rc` gibi, içerdiği
değere yalnızca paylaşılan bir erişim sağlıyor — bir referansın (`&T`) yalnızca okumaya
izin vermesiyle aynı ilke. Kabul edilen yazım, aynı alanı yalnızca **okuyor**.

Bu kısıt aslında `Arc`e özgü değildir; bir önceki derste `Rc` için de aynı kural
geçerliydi, orada açıkça yazılmamıştı çünkü asıl ölçüm sayaçtı. Burada açıkça yazılmasının
nedeni şu: atomik sayaç, "paylaşılan veri artık güvenli biçimde değiştirilebilir" gibi bir
izlenim uyandırabilir, çünkü kelime "atomik" bir güvenceyi çağrıştırır. Ölçüm bu izlenimi
düzeltiyor — güvence yalnızca sayacın kendi tutarlılığı içindir, sayacın koruduğu değerin
içeriği için değil. İki kopya aynı anda aynı veriyi okuyabilir, ama hiçbiri onu tek başına
değiştiremez; değiştirme ihtiyacı ayrı bir araç gerektirir.

**PS9.** — "birden çok kopyanın aynı değeri okuyabildiği ama hiçbirinin onu değiştiremediği"
iddiası, aşağıdaki koşumun iki kopyadan da aynı `deger` alanını basmasıyla ve hiçbir yazma
satırı içermemesiyle doğrulanıyor.

```rust
// paylasilan_veri_salt_okunur.rs — Arc uzerinden yalniz okuma mumkun
use std::sync::Arc;

struct Olcum {
    deger: i64,
}

fn main() {
    let paylasilan = Arc::new(Olcum { deger: 42 });
    let kopya = Arc::clone(&paylasilan);

    println!("ilk okuma: {}", paylasilan.deger);
    println!("kopyadan okuma: {}", kopya.deger);
    println!("sayac: {}", Arc::strong_count(&paylasilan));
}
```

```
ilk okuma: 42
kopyadan okuma: 42
sayac: 2
```

İki kopya da aynı `deger` alanını okuyor ve ikisi de aynı sonucu veriyor, çünkü aslında
tek bir `Olcum` değeri var, iki kopya da ona erişiyor. Bu programda hiçbir satır `deger`
alanına yazmıyor — bu tesadüf değil, `Arc`in izin verdiği tek işlem okumadır. `deger`i
`43` yapmaya çalışan bir satır eklenseydi derlenmezdi; bu redd program içinde ayrıca
koşturulmuyor, çünkü derlenmeyen bir kaynak kod bloğuna konmuyor. Sayaç bu koşumda da
okunuyor (`sayac: 2`), ama bu satırın `deger` alanıyla hiçbir ilişkisi yok — biri kaç
kopya olduğunu, öbürü kopyaların baktığı değerin içeriğini söylüyor; ikisi birbirinden
bağımsız iki farklı soru.

Bu örnekte `Iz`/`defter` düzeneği yerine yalın bir `Olcum` yapısı kullanılıyor, çünkü
ölçülen şey bir bitiş kaydı değil, erişimin kendisi. Öbekte Tekil Sahiplik dersinde bir
`Box` üzerinden `nokta.x` okumanın, değerin doğrudan orada duruyormuş gibi çalıştığı
gösterilmişti; burada da `paylasilan.deger` ve `kopya.deger` aynı satır biçimini
kullanıyor. Fark şu: `Box`ta bu erişim hem okumaya hem yazmaya açıktı, çünkü tek sahip
vardı. `Arc`te aynı erişim yalnızca okumaya açık, çünkü sahiplik paylaşılıyor ve
paylaşılan bir değere kimin ne zaman yazdığını izleyen bir düzenek henüz devrede değil.

Üç ölçüm bir araya geldiğinde şu ortaya çıkıyor: `Arc`, sayaç düzeyinde `Rc`nin
güçlendirilmiş bir biçimidir, ama bu güçlendirme paylaşılan verinin kendisine hiç
sirayet etmez. Sayaç ne kadar sağlam güncellenirse güncellensin, verinin değiştirilebilir
olup olmadığı ayrı bir sorudur ve bu iki türün hiçbirinde henüz yanıtlanmıyor.

Bu konunun ilk üç dersi birlikte okunduğunda bir ilerleme görülüyor. Öbekte Tekil
Sahiplik, bir değerin öbekte durabildiğini ama sahibinin hâlâ tek olduğunu kurdu.
Referans Sayımı, bu tekliği bir sayaçla genişletilebilir hâle getirdi — sahiplik artık
sayılabilir bir kümeydi. Bu ders, o sayacın güncellenme biçimini değiştirilebilir bir
seçenek olarak sundu, ama sahiplik ve erişim modelinin kendisini değiştirmedi: kaç
kopya olursa olsun, hiçbiri değeri değiştiremiyor. Üç ders boyunca kap değişti, sayaç
değişti, ama içindeki değere yazma hakkı hiç doğmadı — bu hakkın nasıl kazanılacağı
kursun bir sonraki ve son sorusu. Üç dersin ortak paydası şu: her birinde bir değerin
ömrü hâlâ kaynaktan okunabiliyor, hiçbiri bu belirlenimciliği bozmuyor — yalnızca sahiplik
biçimi ve erişim hakkı derece derece genişliyor.

#### Özet

- `Arc<T>`, `Rc<T>` ile aynı arayüzü taşır ve aynı "sayaç sıfıra inince değer biter"
  kuralını uygular.
- İki türün ürettiği bitiş kaydı ve sayaç dizisi birebir aynıdır — ikisinde de değerin
  ömrü **kabıyla birlikte** bitiyor; fark davranışta değil,
  sayacın atomik olarak güncellenmesindedir.
- Atomik güncellemenin hangi bağlamda gerektiği bu dersin konusu değildir, M10/K04'ündür.
- `Arc` üzerinden paylaşılan veri yalnızca okunabilir; bir alana doğrudan yazmak
  derlenmez.
- Atomik sayaç veriyi değil, yalnızca kendisini korur; paylaşılan verinin değiştirilemez
  kalması ayrı bir kısıttır.
- Her `Arc` değerinin kendi sayacı vardır ve bitiş, hangi kopyanın değil kaç kopyanın
  kaldığına bağlıdır — bu ilke `Rc` ile aynıdır.

#### Sonraki Adım

Bu derste paylaşılan bir değerin okunabildiği ama değiştirilemediği ölçüldü. Bir sonraki
soru kaçınılmaz: paylaşılan bir değeri değiştirmek gerekirse ne olur? Değişkenler ve
Değişmezlik dersinde bir sınır açık bırakılmıştı: bağlamanın değişmezliği ile içindeki bir
alanın değişebilirliği ayrı sorulardı ve o ders yalnızca sınırı çizmişti, kapatmamıştı.
Sıradaki (ve bu konunun son) ders, ödünç denetiminin derleme zamanından çalışma zamanına
nasıl taşınabildiğini ve bu taşımanın hangi bedeli getirdiğini ölçerek o sınırı kapatıyor.

### İç Değişebilirlik

Source: https://academia.sh/tr/kurslar/sahiplik/ic-degisebilirlik

Aynı 'bir yazan ya da çok okuyan' kuralının derleme zamanı yerine çalışma zamanında, bir sayaçla sınandığı ölçülüyor; bir bağlamanın kendisi değişmezken içindeki değerin RefCell ile değişebildiği ve başarısız bir ödünç denemesinin panik değil bool sonucuyla alınabildiği gösteriliyor. Kural kaybolmuyor, yer değiştiriyor.

Önceki üç ders boyunca paylaşılan bir değer hep okunabildi; `Rc` ve `Arc`ta hiç
değiştirilemedi, `Box`ta ise tek sahip olduğu için (bağlama `mut` alırsa) değiştirme zaten
mümkündü. Değişkenler ve Değişmezlik dersi de bir soru açık bırakmıştı: bir bağlamanın `mut`
almamasının, o bağlamanın **kendi adı üzerinden** hiçbir değişikliğe izin vermeyeceğini garanti
ettiği kurulmuştu, ama aynı verinin başka bir bağlama ya da referans üzerinden paylaşılıp
paylaşılamayacağı, paylaşılırsa değişmezliğin oradan da geçerli olup olmayacağı sorusu bu kursa
(K02) bırakılmıştı. Bu ders tam o soruyu yanıtlıyor: bir değeri, sahiplik paylaşılırken de,
bağlama değişmez görünürken de değiştirmenin bir yolu var mı? Bu kursta ölçülen hep aynı
kalıyor — bir değerin nerede bittiği —, Eşzamanlılık kursunda (M09/K03) ölçülen koşan bir
birimin nasıl duracağı değil.

Yanıt evet, ama bu değişikliğin bir bedeli var; bu ders o bedeli ölçüyor ve bu konunun son
dersi olarak konunun dört ölçümünü de bir araya getiriyor.

Atomik Referans Sayımı dersi bu ihtiyacı açıkça bıraktı: `Arc` üzerinden bir alana
yazmaya çalışan bir satır derlenmiyordu, çünkü paylaşılan bir değere aynı anda kaç
kopyanın erişebileceğini bilmenin, o değeri güvenle değiştirmek için yeterli olmadığı
gösterilmişti. Aynı sınır `Rc` için de geçerliydi — `Box`ta tek sahip olduğu için
değiştirme zaten mümkündü (bağlama `mut` alırsa), ama `Rc` ve `Arc`ta paylaşım başladığı
andan itibaren yazma kapandı, çünkü ikisi de içerdikleri değere yalnızca paylaşımlı
erişim veriyordu. Bu derste o kapı yeniden açılıyor, ama farklı bir anahtarla: tipin
kendisinden değil, çalışma zamanında sınanan bir izinden geçerek.

#### Kuralın Yer Değiştirmesi

Ödünç Denetleyicisi dersi, "aynı anda ya bir değiştirilebilir referans ya da birden çok
paylaşımlı referans" kuralının derleme zamanında sınandığını gösterdi: bu kuralı ihlal
eden bir yazım hiç derlenmiyordu. `RefCell<T>`, aynı kuralı **çalışma zamanına** taşıyan
bir kaptır. İçindeki değere `borrow()` ile paylaşımlı, `borrow_mut()` ile değiştirilebilir
erişim istenir; `RefCell` bu istekleri bir sayaçla izler ve kuralı ihlal eden bir istek
derlenmez değil, çalışma zamanında **reddedilir**.

Bu derste redd bir panikle değil, `try_borrow()` ve `try_borrow_mut()` çağrılarının
döndürdüğü bir sonuçla ölçülüyor: istek uygunsa `Ok`, değilse `Err`. Panik metni hiçbir
yerde basılmıyor; yalnızca isteğin başarılı olup olmadığı bir `bool` olarak yazdırılıyor.

`RefCell` de, tıpkı `Rc` ve `Arc` gibi, bir sayaç tutar — ama sayılan şey farklıdır. `Rc`
ve `Arc`ın sayacı kaç **sahibin** olduğunu sayıyordu ve sıfıra inince değer bitiyordu.
`RefCell`in sayacı kaç **aktif ödüncün** olduğunu sayar ve değeri hiç bitirmez; yalnızca
o an hangi tür erişimin (paylaşımlı mı, değiştirilebilir mi) sürdüğünü izler. Bu iki
sayaç birbirinden bağımsız çalışabilir: bir `Rc<RefCell<T>>` değeri hem kaç kopyasının
olduğunu hem de o an kimin onu ödünç aldığını, iki ayrı sayaçla aynı anda tutabilir. Bir
kopya bitip sahiplik sayacı azalırken, ödünç sayacı o kopyanın o an bir ödünç tutup
tutmadığından tamamen habersizdir — ikisi ayrı soruları yanıtlıyor.

#### Bağlamanın Değişmezliği İçeriği Bağlamıyor

Aşağıdaki koşum bunu doğrudan gösteriyor: `sayac` adlı bağlama `mut` **değil**, ama
içindeki tam sayı yine de değişiyor.

**PS10.** — "bağlamanın kendisi değişmezken içindeki değerin değişebildiği" iddiası,
aşağıdaki koşumda `let sayac: RefCell<i64> = RefCell::new(0);` satırının `mut` içermemesine
rağmen `ilk yazimdan sonra deger: 1` satırının basılmasıyla doğrulanıyor.

```rust
// odunc_zaman_kaydirmasi.rs — derleme zamaninda reddedilen kural, calisma zamaninda bir sonuca donusuyor
use std::cell::RefCell;

fn main() {
    let sayac: RefCell<i64> = RefCell::new(0); // baglama mut degil

    {
        let mut yazan = sayac.borrow_mut();
        *yazan += 1;
    }
    println!("ilk yazimdan sonra deger: {}", sayac.borrow());

    let ilk_okuma = sayac.borrow();
    let ikinci_okuma = sayac.borrow();
    println!("iki okuma birlikte: {} ve {}", *ilk_okuma, *ikinci_okuma);

    let yazma_denemesi = sayac.try_borrow_mut();
    println!("okuma surerken yazma denemesi basarili mi: {}", yazma_denemesi.is_ok());

    drop(ilk_okuma);
    drop(ikinci_okuma);

    let ikinci_yazma_denemesi = sayac.try_borrow_mut();
    println!(
        "okumalar birakildiktan sonra yazma denemesi basarili mi: {}",
        ikinci_yazma_denemesi.is_ok()
    );
}
```

```
ilk yazimdan sonra deger: 1
iki okuma birlikte: 1 ve 1
okuma surerken yazma denemesi basarili mi: false
okumalar birakildiktan sonra yazma denemesi basarili mi: true
```

`sayac` bağlaması hiçbir yerde `mut` taşımıyor, ama `borrow_mut()` çağrısı içindeki değeri
gerçekten değiştiriyor. Değişkenler ve Değişmezlik dersi, `mut` almamanın **adın kendisi
üzerinden** hiçbir değişikliğe izin vermeyeceğini kurmuştu; `RefCell` bu garantiyi
bozmuyor — `sayac` adının kendisi hâlâ yeniden bağlanamıyor, hiçbir alanı sıradan bir
atamayla değiştirilemiyor. `borrow_mut()`, adın kendisinden değil, `RefCell`in çalışma
zamanında kontrol ettiği ayrı bir kapıdan giriyor. `ilk_okuma` ve `ikinci_okuma` aynı anda
yaşarken ikisi de aynı değeri okuyabiliyor — "çok okuyan" izinli. Onlar hâlâ yaşarken
gelen yazma denemesi başarısız oluyor; ikisi de bırakıldıktan sonra aynı deneme başarılı
oluyor. Kural aynı: bir yazan ya da çok okuyan, ikisi birden değil.

#### İki Yazan da Aynı Kuralı İhlal Eder

Kural yalnızca "yazarken okunmasın" değil, "aynı anda iki yazan olmasın" kısmını da
kapsıyor. Aşağıdaki koşum bunu ayrıca sınıyor: bir değiştirilebilir ödünç sürerken ikinci
bir değiştirilebilir ödünç istendiğinde de aynı redd oluyor.

**PS11.** — "aynı anda iki değiştirilebilir ödüncün de reddedildiği" iddiası, aşağıdaki
koşumun `ilk yazan aktifken ikinci yazma denemesi basarili mi: false` satırıyla
doğrulanıyor.

```rust
// iki_yazici_denemesi.rs — ayni anda iki degistirilebilir odunc de reddediliyor
use std::cell::RefCell;

fn main() {
    let veri: RefCell<Vec<i32>> = RefCell::new(vec![1, 2, 3]);

    let mut ilk_yazan = veri.borrow_mut();
    ilk_yazan.push(4);

    let ikinci_yazma_denemesi = veri.try_borrow_mut();
    println!(
        "ilk yazan aktifken ikinci yazma denemesi basarili mi: {}",
        ikinci_yazma_denemesi.is_ok()
    );
    drop(ilk_yazan);

    let simdi_basarili_mi = veri.try_borrow_mut();
    println!("ilk yazan birakildiktan sonra basarili mi: {}", simdi_basarili_mi.is_ok());
    drop(simdi_basarili_mi);
    println!("veri uzunlugu: {}", veri.borrow().len());
}
```

```
ilk yazan aktifken ikinci yazma denemesi basarili mi: false
ilk yazan birakildiktan sonra basarili mi: true
veri uzunlugu: 4
```

`ilk_yazan` hâlâ elde tutulurken açılan ikinci deneme de reddediliyor — bu kez çakışan iki
okuma değil, iki yazma isteği. `ilk_yazan` üzerinden `veri`ye bir eleman eklenmiş olması
(`push(4)`), koruyucunun bırakıldığı anda kalıcı hâle geliyor: son satırdaki uzunluk dört.
Sayaç, kaç okuyucunun aktif olduğunu değil, aktif erişimin **türünü** de ayırt ediyor —
bir yazan varken ne başka bir yazan ne de bir okuyan kabul ediliyor.

Bu iki koşum (önceki bölümdeki ve bu bölümdeki) birlikte kuralın tamamını kapsıyor: çok
okuyan izinliyken, bir okuyanla bir yazan da, iki yazan da izinsizdi. Üç durumun ikisi
`try_borrow` ya da `try_borrow_mut`in `Err` döndürmesiyle, kalanı `Ok` döndürmesiyle
ölçüldü; hiçbirinde panik metni basılmadı, hiçbirinde program çökmedi. Ödünç
Denetleyicisi dersinde derleme zamanında reddedilen "okurken değiştirme" ihlali, burada
aynı adla, ama çalışma zamanında bir `Err` olarak karşımıza çıkıyor.

#### Kural Kaybolmuyor, Yer Değiştiriyor

Ödünç Denetleyicisi dersindeki üç redd örneğinin hiçbiri kod bloğuna girmedi — hepsi
düzyazıda tarif edildi, yanlarına kabul edilen çözüm kondu; ihlal eden kaynak hiçbir zaman
derlenmedi. Burada aynı ihlal türü — bir değer yazılırken aynı değere başka bir erişim
istenmesi — gerçekten **derleniyor**; yalnızca çalışma zamanında `Err` üretiyor. Bu,
kuralın ortadan kalktığı anlamına gelmiyor: derleme zamanında kaçınılan bir hata, çalışma
zamanında bir sonuca dönüşüyor. Yukarıdaki koşumun `false` basan yazma denemesi satırı,
Ödünç Denetleyicisi dersinde hiç derlenmeyecek türden bir ihlalin burada derlendiğini ve
çalışma zamanında yakalandığını gösteriyor — program çökmüyor, çünkü redd
`try_borrow_mut` ile panik yerine bir `Result`e dönüştürülüyor.

Bu değiş tokuşun bedeli şudur: derleme zamanındaki denetim, bir yazımı çalıştırmadan önce
eler; çalışma zamanındaki denetim, aynı ihlali ancak o satır çalıştığında yakalar. Yanlış
kod artık derlenmiyor değil, çalışırken kendi başarısızlığını bildiriyor — ama bu bildirim
ancak o satıra gelindiğinde olur; ihlale hiç uğramayan bir çalıştırma, sorunu hiç
göstermez. Ödünç Denetleyicisi dersinde ölçülen "denetleyici doğruluğu değil, sahiplik
disiplinini güvence altına alır" ilkesi burada bir adım daha ileri gidiyor: çalışma
zamanı denetimi de yalnızca **çalışan yolu** sınıyor, kodun hiç uğramadığı bir satırdaki
ihlali göremiyor.

#### Defterin Kendisi Bu Derste Açıklanıyor

Değişkenler ve Değişmezlik dersinin K02'ye bıraktığı soru tam olarak buydu: aynı veri
başka bir bağlama ya da referans üzerinden paylaşıldığında, değişmezlik oradan da geçerli
mi kalıyor? Bu kursun bütün derslerinde kullanılan `defter`, bu sorunun yanıtını baştan
beri örtük olarak taşıyordu. `defter`, `Rc<RefCell<Vec<String>>>` tipinde bir değerdi.
Referans Sayımı dersi `Rc` kısmını, bu ders `RefCell` kısmını açıklıyor: `defter`
paylaşılıyordu (`Rc`) ve içeriği değiştirilebiliyordu (`RefCell`) — iki kap iç içe
kullanılarak hem paylaşım hem değişebilirlik aynı anda sağlanıyordu.

**PS12.** — "bir işlevin `&Defter` alıp içeriği değiştirebildiği" iddiası, aşağıdaki
koşumda `kayit_ekle` işlevinin parametresinin `&Defter` olmasına (değiştirilebilir referans
değil) rağmen `kayit sayisi: 2` satırının basılmasıyla doğrulanıyor.

```rust
// defterin_ic_degisebilirligi.rs — bu kurs boyunca kullanilan defter tipi boyle calisiyordu
use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz {
            ad: ad.to_string(),
            defter: Rc::clone(defter),
        }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

fn kayit_ekle(defter: &Defter, metin: &str) {
    // defter parametresi & ile alindi, mut degil; yine de icerik degisiyor.
    defter.borrow_mut().push(metin.to_string());
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));
    kayit_ekle(&defter, "elle-eklenen");
    {
        let _olcum = Iz::yeni("birakildiginda-eklenen", &defter);
    }
    let kayit = defter.borrow();
    println!("kayitlar: {}", kayit.join(", "));
    println!("kayit sayisi: {}", kayit.len());
}
```

```
kayitlar: elle-eklenen, birakildiginda-eklenen
kayit sayisi: 2
```

`kayit_ekle` işlevi `defter: &Defter` alıyor — `&Rc<RefCell<Vec<String>>>`, yani sıradan
bir paylaşımlı referans. Buna rağmen `defter.borrow_mut().push(...)` çağrısı listeye
gerçekten bir eleman ekliyor. Bu, kursun ilk dersinden beri her `Iz::drop` çağrısının
yaptığı şeyin ta kendisidir: `drop` işlevi `&mut self` alsa bile, `self.defter` bir `Rc`
olduğu için doğrudan değiştirilemiyordu — `self.defter.borrow_mut().push(...)` satırı,
`&mut self`in kendi verdiği erişimi değil, `RefCell`in verdiği çalışma zamanı erişimini
kullanıyordu. Kursun başından beri koşan her koşum, aslında bu dersin ölçtüğü düzeneği
arka planda kullanıyordu — yalnızca bu ders o düzeneği açıkça adlandırıyor.

Bu, `defter`in neden `Vec<String>` değil de `Rc<RefCell<Vec<String>>>` olarak
tanımlandığını da açıklıyor. `Vec<String>` tek başına ne paylaşılabilir ne de birden
çok yerden değiştirilebilir olurdu — bir işlevin ya sahibi olması ya da ona sıradan bir
referans vermesi gerekirdi ve sıradan bir referansla `push` çağırmak `&mut` gerektirirdi.
`Rc` paylaşımı, `RefCell` değişebilirliği getirdi; ikisi birlikte, `Iz::yeni` her
çağrıldığında yalnızca `&Defter` geçirilmesine rağmen her `Iz` kendi bitişini aynı listeye
yazabildi. Kursun ilk üç dersi bu iç içe kabın yalnızca `Rc` yarısını konu etti; bu ders
öbür yarısını tamamlıyor.

#### Erişim Şeffaf Değil, Açık Bir Çağrı Gerektiriyor

Öbekte Tekil Sahiplik dersi, bir `Box` içindeki alanlara doğrudan erişilebildiğini
gösterdi: `nokta.x` yazımı, değer öbekte olsa da olmasa da aynıydı. Atomik Referans Sayımı
dersinde de `paylasilan.deger` doğrudan okunabiliyordu. `RefCell` bu şeffaflığı
sürdürmüyor: içindeki değere doğrudan `hucre.alan` yazılarak erişilemez, önce `borrow()`
ya da `borrow_mut()` çağrılıp bir koruyucu değer alınması gerekir. Bu fark rastlantı
değil — `Box`, `Rc` ve `Arc` içindeki değere erişimin **her zaman güvenli** olduğunu
derleme zamanında biliyordu, bu yüzden erişimi gizleyebiliyordu. `RefCell` ise güvenliği
ancak çalışma zamanında, her çağrıda yeniden sınıyor; bu sınamanın kaynakta **görünür**
olması gerekiyor, çünkü sınama başarısız da olabilir.

Bu görünürlük, `try_borrow_mut`in döndürdüğü `Result` değerinde somutlaşıyor: bir `Box`
alanına yazmak asla başarısız olmayan bir işlemken, bir `RefCell`e yazmak denenip
**sonucu kontrol edilmesi gereken** bir işlemdir. Kod bu farkı gizleyemiyor — çağıran
taraf, isteğinin kabul edilip edilmediğini bir sonraki satırda ele almak zorunda kalıyor.
Bu, kursun üç ölçüm boyunca izlediği bir düzenin son adımıdır: bir işlemin ne zaman
kesin, ne zaman koşullu olduğu, o işlemin döndürdüğü tipten okunabiliyor — `()` her zaman
başarır, `Result` başarabilir ya da başarısız olabilir.

Dört ölçüm bir araya geldiğinde konunun bütün resmi ortaya çıkıyor. Öbekte Tekil Sahiplik,
bir değerin öbekte durabildiğini ama sahibinin tek kaldığını kurdu. Referans Sayımı, bu
tekliği sayılabilir bir çokluğa açtı. Atomik Referans Sayımı, bu sayımın farklı
bağlamlarda da aynı sonucu verdiğini, ama paylaşılan verinin hâlâ değiştirilemez
kaldığını gösterdi. Bu ders, o son kısıtı bir bedelle kaldırdı: değiştirme artık mümkün,
ama artık her deneme bir sonuç döndürüyor ve o sonucun kontrol edilmesi gerekiyor. Konu
boyunca hiçbir adımda belirlenimcilik kaybolmadı — her bitiş, her sayaç değişimi, her
ödünç denemesi, koşumda aynı sırayla, aynı sonuçla üretildi.

#### Özet

- `RefCell<T>`, "bir yazan ya da çok okuyan" kuralını derleme zamanı yerine çalışma
  zamanında, bir sayaçla sınayan bir kaptır; içindeki değerin ömrü **kabıyla birlikte**
  bitiyor.
- Bir bağlamanın kendisi `mut` olmasa da, `RefCell` ile içindeki değer değişebilir; adın
  kendisi hâlâ yeniden bağlanamaz, değişim ayrı bir kapıdan geçer.
- Aynı veri birden çok bağlama (`Rc` kopyası) arasında paylaşıldığında da `RefCell` ile
  değiştirilebilir; bu, K01'in K02'ye bıraktığı "paylaşımda değişmezlik ne olur" sorusunu
  yanıtlar — kursun başından beri kullanılan `defter` tipi tam olarak bu düzenekti.
- Başarısız bir ödünç denemesi panikle değil, `try_borrow`/`try_borrow_mut`in döndürdüğü
  bir sonuçla ölçülür.
- Kural kaybolmaz, yer değiştirir: derleme zamanında kaçınılan bir ihlal, çalışma
  zamanında bir sonuca (`Err`) dönüşür.
- `RefCell` üzerinden erişim şeffaf değildir; her erişim açık bir `borrow` çağrısı
  gerektirir, çünkü çağrı her zaman başarılı olmayabilir.

#### Sonraki Adım

Bu konunun dört dersi boyunca bir değerin sahipliği çoğaldı, sayıldı, atomikleşti ve en
sonunda paylaşılırken değiştirilebilir hâle geldi — ama her seferinde tek bir varsayım
hiç sorgulanmadı: paylaşan değerler birbirinden bağımsızdı, hiçbiri bir ötekini
**tutmuyordu**. Her sayaç, kendi değerine ait kalan kopyaları sayıyordu; hiçbir kopya,
sayılan değerin kendisini geriye doğru tutmuyordu. Kursun son sorusu tam bunu soruyor: ya
iki değer, `RefCell` üzerinden birbirinin içine birer `Rc` koyarak birbirini tutarsa?
Sayaç o zaman hâlâ sıfıra inebilir mi, yoksa hiç inemez mi?

### Döngüsel Referanslar

Source: https://academia.sh/tr/kurslar/sahiplik/dongusel-referanslar

İki değer RefCell üzerinden birbirini Rc ile tuttuğunda güçlü sayacın hiçbir zaman sıfıra inmediği ve defterde hiçbir kaydın oluşmadığı ölçülüyor — kursun tek sızıntısı. Bir zayıf referansın sayacı artırmadan aynı döngüsel referansı kırdığı ve kırıldıktan sonra defterde iki kaydın birden oluştuğu koşturuluyor; güçlü ve zayıf sayaç değerleri basılıyor.

Kursun üç konusu ve on üç dersi boyunca bir değerin ömrü hep dört sınıftan birine düştü ve
sıfırıncı bir seçenek hiç görülmedi — `Rc` ile `Arc`ın sayacı bile, kaç kez kopyalanırsa
kopyalansın, er ya da geç sıfıra indi. Bu son ders tam bu varsayımı bozan tek durumu ölçüyor:
iki değer, `RefCell` üzerinden birbirinin içine birer `Rc` koyarsa, güçlü sayaç hiçbir zaman
sıfıra inmiyor ve defterde hiçbir kayıt oluşmuyor. Kursun on üç dersi boyunca ölçülen her
bitiş kaynaktan okunabilir, belirlenimci bir noktaya sahipti; bu ders o belirlenimciliğin
kendi sınırını — bir bitişin hiç gerçekleşmeyebileceğini — gösteriyor.

Eşzamanlılık kursunda (M09/K03) ölçülen sızıntı, durması beklenen ama hiç durmayan bir
goroutine'di: koşan bir birim sızıyordu. Burada sızan bir birim değil bir değer — kaynak
kodun kendisi tamamen sıradan biçimde biter, program sonlanır, ama iki `Dugum` değeri bu
sondan sonra da bellekte kalır, hiçbir zaman bırakılmaz.

#### İki Değer Birbirini Tutunca

Çekirdeğin `Defter`, `Iz` ve `Drop` uygulaması burada da aynı kesitle kullanılıyor. Üstüne
tek bir yeni tip ekleniyor: `Dugum`, kendi `Iz`sini ve bir sonraki düğüme güçlü bir referans
tutan `sonraki: RefCell<Option<Rc<Dugum>>>` alanını taşıyor. İki `Dugum` değeri (`a`, `b`)
`Rc::new` ile kuruluyor, sonra her biri ötekine `Rc::clone` ile bir referans veriyor —
Referans Sayımı dersinde ölçülen kopyalama işleminin ta kendisi, burada
yalnızca karşılıklı yönde uygulanıyor.

**PS13.** — "iki değerin birbirini tuttuğunda güçlü sayacın kapsam kapandıktan sonra bile
sıfıra inmediği" iddiası, aşağıdaki koşumun `kapsam kapaninca defter uzunlugu: 0`
satırıyla doğrulanıyor.

```rust
// dongu_olusumu.rs — iki degerin birbirini tutmasi: sayac hic sifira inmiyor, defter bos kaliyor
use std::cell::RefCell;
use std::rc::Rc;

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz { ad: ad.to_string(), defter: Rc::clone(defter) }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

struct Dugum {
    iz: Iz,
    sonraki: RefCell<Option<Rc<Dugum>>>,
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));

    {
        let a = Rc::new(Dugum {
            iz: Iz::yeni("dugum-a", &defter),
            sonraki: RefCell::new(None),
        });
        let b = Rc::new(Dugum {
            iz: Iz::yeni("dugum-b", &defter),
            sonraki: RefCell::new(None),
        });

        *a.sonraki.borrow_mut() = Some(Rc::clone(&b));
        *b.sonraki.borrow_mut() = Some(Rc::clone(&a));

        println!("a adi: {}, sayac: {}", a.iz.ad, Rc::strong_count(&a));
        println!("b adi: {}, sayac: {}", b.iz.ad, Rc::strong_count(&b));
    }

    println!("kapsam kapaninca defter uzunlugu: {}", defter.borrow().len());
}
```

```
a adi: dugum-a, sayac: 2
b adi: dugum-b, sayac: 2
kapsam kapaninca defter uzunlugu: 0
```

Kap dolu iken sayaç ikisinde de iki: `a`nın kendi bağlaması bir, `b.sonraki`nin tuttuğu
kopya bir; `b` için de simetrik. Kapsam kapanınca `a` ve `b` bağlamaları bildirimin tersi
sırayla bitiyor — Yığıt ve Öbek dersinde kurulan kural burada da geçerli. Ama her
bağlamanın bitmesi yalnızca kendi sayacını bir azaltıyor: `b` bittiğinde `a.sonraki`nin
tuttuğu kopya hâlâ `b`nin `Dugum`ını canlı tutuyor; `a` bittiğinde de `b.sonraki`nin
tuttuğu kopya `a`nınkini. Geriye kalan sayaç ikisinde de bir — hiçbir zaman sıfır olmuyor.
`Dugum::iz` alanının `Drop`u bu yüzden hiç tetiklenmiyor, çünkü `Dugum`ın kendisi hiç
bırakılmıyor; defter, koşumun sonuna kadar boş kalıyor.

#### Zayıf Referans Sayacı Artırmıyor, Döngüsel Referansı Kırıyor

Bu döngüsel referansı kırmanın yolu, iki yönden birini **zayıf** bir referansa çevirmek:
`Weak<T>`, `Rc<T>` gibi aynı değere işaret eder ama güçlü sayacı hiç artırmaz. `Dugum`
burada ikiye ayrılıyor — `guclu_sonraki` bir yönü güçlü tutuyor, `zayif_onceki` öbür yönü
zayıf tutuyor. Hangi yönün zayıf olacağı bir tasarım kararı; dilin kendiliğinden verdiği
bir yanıt değil.

**PS14.** — "bir zayıf referansın güçlü sayacı hiç artırmadığı" iddiası, aşağıdaki koşumun
`a adi: kirilan-a, guclu: 1, zayif: 1` satırıyla doğrulanıyor: `b`, `a`ya zayıf referans
tutuyor ve `a`nın güçlü sayacı hâlâ bir.

```rust
// zayif_ile_kirma.rs — zayif referans sayaci artirmiyor ve dongusel referansi kiriyor
use std::cell::RefCell;
use std::rc::{Rc, Weak};

type Defter = Rc<RefCell<Vec<String>>>;

struct Iz {
    ad: String,
    defter: Defter,
}

impl Iz {
    fn yeni(ad: &str, defter: &Defter) -> Iz {
        Iz { ad: ad.to_string(), defter: Rc::clone(defter) }
    }
}

impl Drop for Iz {
    fn drop(&mut self) {
        self.defter.borrow_mut().push(self.ad.clone());
    }
}

struct Dugum {
    iz: Iz,
    guclu_sonraki: RefCell<Option<Rc<Dugum>>>,
    zayif_onceki: RefCell<Weak<Dugum>>,
}

fn main() {
    let defter: Defter = Rc::new(RefCell::new(Vec::new()));

    {
        let a = Rc::new(Dugum {
            iz: Iz::yeni("kirilan-a", &defter),
            guclu_sonraki: RefCell::new(None),
            zayif_onceki: RefCell::new(Weak::new()),
        });
        let b = Rc::new(Dugum {
            iz: Iz::yeni("kirilan-b", &defter),
            guclu_sonraki: RefCell::new(None),
            zayif_onceki: RefCell::new(Weak::new()),
        });

        *a.guclu_sonraki.borrow_mut() = Some(Rc::clone(&b));
        *b.zayif_onceki.borrow_mut() = Rc::downgrade(&a);

        println!("a adi: {}, guclu: {}, zayif: {}", a.iz.ad, Rc::strong_count(&a), Rc::weak_count(&a));
        println!("b adi: {}, guclu: {}, zayif: {}", b.iz.ad, Rc::strong_count(&b), Rc::weak_count(&b));

        let geri_donen = b.zayif_onceki.borrow().upgrade();
        println!("b uzerinden a'ya geri donus basarili mi: {}", geri_donen.is_some());
    }

    println!("kapsam kapaninca defter: [{}]", defter.borrow().join(", "));
}
```

```
a adi: kirilan-a, guclu: 1, zayif: 1
b adi: kirilan-b, guclu: 2, zayif: 0
b uzerinden a'ya geri donus basarili mi: true
kapsam kapaninca defter: [kirilan-a, kirilan-b]
```

`a`nın güçlü sayacı bir kalıyor, çünkü yalnızca kendi bağlaması ona sahip; `b`nin zayıf
sayacı bir, çünkü `b.zayif_onceki` ona bakıyor ama sahiplenmiyor. `b`nin güçlü sayacı ise
iki — kendi bağlaması ve `a.guclu_sonraki`nin tuttuğu kopya. `upgrade()` çağrısı, zayıf
referansın hâlâ geçerli bir değere baktığını doğruluyor: bir `Option<Rc<Dugum>>`
döndürüyor ve `a` hâlâ yaşadığı için sonuç `Some`.

**PS15.** — "bu döngüsel referans kırıldıktan sonra defterde iki kaydın birden oluştuğu"
iddiası, aynı koşumun son satırındaki `defter: [kirilan-a, kirilan-b]` ile doğrulanıyor.

Kapsam kapanınca `b` önce bitiyor ve güçlü sayacını ikiden bire indiriyor — `a.guclu_sonraki`
hâlâ bir kopya tuttuğu için `b`nin `Dugum`ı henüz bırakılmıyor. `a` bitince kendi sayacı
sıfıra iniyor ve gerçekten bırakılıyor; bu bırakma önce kendi `iz` alanını (`kirilan-a`)
deftere yazıyor, sonra kendi `guclu_sonraki` alanını bırakırken `b`ye olan son güçlü
referansı da düşürüyor — `b`nin sayacı da sıfıra iniyor ve `b` de bırakılıyor
(`kirilan-b`). Zayıf referans bu zincire hiç girmiyor: `b.zayif_onceki` bırakılırken hiçbir
güçlü sayaç değişmiyor, çünkü zaten hiç saymamıştı.

#### Sınırlayıcı Ölçüm: Derleyici Döngüsel Referansı Görmüyor

Yukarıdaki iki koşum arasındaki fark, kaynakta hiçbir redd olmadan geçiyor. `dongu_olusumu.rs`
da, `zayif_ile_kirma.rs` de aynı satırlarla derleniyor: `Rc::new`, `Rc::clone`, bir
`RefCell` alanına yazma — Referans Sayımı dersinden beri (PS5) kullanılan işlemlerin ta
kendisi. Ödünç Denetleyicisi dersi, denetleyicinin sahiplik disiplinini sınadığını ama
kodun doğruluğunu güvence altına almadığını göstermişti; burada aynı sınır bir adım daha
genişliyor: derleyici, iki `Rc` değerinin birbirini tuttuğunu hiçbir zaman fark etmiyor,
çünkü her `Rc::clone` çağrısı kendi başına geçerli bir işlem — sayaç artırma, hangi değere
işaret ettiğine bakmaksızın izin veriliyor.

**PS16.** — "birbirini tutan bir kaynağın, birbirini tutmayan bir kaynakla aynı derleme
yolundan geçtiği" iddiası, iki koşumun da (`dongu_olusumu`, `zayif_ile_kirma`) hiçbir uyarı
ya da hata vermeden derlenmesiyle doğrulanıyor.

Bu, kursun bütün derslerinde ölçülen belirlenimciliğin bir istisnası değil, kendi sınırı:
bitiş noktası hâlâ kaynaktan okunabiliyor, yalnız bu kez okunan şey bir bitişin **hiç yer
almayacağı**. Döngüsel referansı kırmak bu yüzden derleyicinin değil yazanın sorumluluğu;
hangi yönün zayıf olacağını seçmek de öyle — `b`nin `a`yı zayıf tutması yerine `a`nın
`b`yi zayıf tutması seçilseydi aynı kırılma ters yönde gerçekleşirdi, sonuç değişmezdi.

#### Kapanış Tablosu

On dört ders boyunca ölçülen on dört bitiş noktası aşağıda toplanıyor. Her satırın sınıfı
ilgili dersin kendi metninde yazılıdır; tablo yeni bir sınıflama yapmıyor, dağınık olanı bir
araya getiriyor.

| Ders | Ölçülen değer | Ömrün bittiği yer | Sınırlayıcı ölçüm |
|---|---|---|---|
| Yığıt ve Öbek | `kapsam-1/2/3` bitiş sırası | kapsam sonu | bitiş sırası bildirimin tam tersi |
| Sahiplik ve Taşıma | `islev-icine`, `ic-kapsama`, `yapi-icine` | taşındığı yerde | taşıma kopyalama değil, defterde tek kayıt |
| Ödünç Alma | `odunc-1` (paylaşımlı + değiştirilebilir ödünç) | kapsam sonu | ödünç ömrü uzatmaz, referans kaynağı aşamaz |
| Dilimler | `goruntu` (liste dilimi) | kapsam sonu | dilim yalnız aralığı değil kaynağın tamamını kilitler |
| Ödünç Denetleyicisi | `ekle_ve_say` dönüş değeri | kapsam sonu | denetleyici doğruluğu değil erişim disiplinini sınar |
| Yaşam Süresi Kavramı | `r1`, `r2`, `r3` referans aralığı | kapsam sonu | iki bağımsız aralık iç içe olmak zorunda değil |
| Açık Yaşam Süresi Açıklamaları | `oncelikli_ad`, `digerinin_adi` | kapsam sonu | açıklama bir istektir, sözü tutmayan gövde reddedilir |
| Yaşam Süresi Çıkarım Kuralları | `ilk_uc_harf`, `daha_uzun_olan` | kapsam sonu | çıkarım kolaylıktır, kapsamadığı imzada açıklama zorunlu |
| Yapılarda Referans Tutma | `SahipYapi`, `OduncYapi` | taşındığı yerde | yapı, yaşam süresi parametresi olmadan referans taşıyamaz |
| Öbekte Tekil Sahiplik | `obekteki-tekil`, `liste-1..3` | kabıyla birlikte | aynı tip iki farklı sınıfa düşebilir, sınıf işlemden gelir |
| Referans Sayımı | `paylasilan` (Rc) sayacı: 1, 2, 3, 2 | kabıyla birlikte | bitişi belirleyen kopyanın kimliği değil kalan sayısı |
| Atomik Referans Sayımı | `paylasilan` (Arc) sayacı: 1, 2, 3, 2 | kabıyla birlikte | atomik sayaç veriyi değil yalnız sayacı korur |
| İç Değişebilirlik | `sayac` (RefCell) ödünç denemeleri | kabıyla birlikte | kural kaybolmuyor, çalışma zamanında `Err`e dönüşüyor |
| Döngüsel Referanslar | `dugum-a`, `dugum-b` (birbirini tutan) | hiç bitmedi | derleyici görmüyor, aynı `Rc::clone` hem paylaşımı hem sızıntıyı kurar |

#### Özet

- İki değer `Rc` ile birbirini tuttuğunda güçlü sayaç hiçbir zaman sıfıra inmiyor; defterde
  kayıt oluşmuyor — kursun tek sızıntısı.
- Zayıf referans (`Weak<T>`) aynı değere işaret eder ama güçlü sayacı hiç artırmaz; bir
  yönü zayıf tutmak döngüsel referansı kırmaya yetiyor.
- Döngüsel referans kırıldıktan sonra kapsam kapanınca her iki değer de bırakılır ve
  defterde iki kayıt birden oluşur.
- Derleyici bu döngüsel referansı hiçbir zaman reddetmiyor; `Rc::clone` ve `RefCell`
  yazımı, karşılıklı olmayan kullanımla aynı derleme yolundan geçiyor.
- M09/K03'te sızan şey koşan bir birimdi, burada sızan bir değer; ikisi de dışarıdan bir
  sinyal gelmeden kendiliğinden sona ermiyor.

#### Kurs Kapanışı

On dört ders boyunca bu kurs tek bir soruyu sordu: bir değerin ömrü nerede bitiyor? Yanıt her
zaman kaynaktan okunabilir kaldı — kapsam sonunda, taşındığı yerde, açık bir çağrıda, bir
kabıyla birlikte ya da, bu derste görüldüğü gibi, hiç. Kursun ilk konusu, Sahiplik Kuralları,
bu sınıfları ve onları koruyan ödünç denetleyicisini kurdu; ikinci konusu, Yaşam Süreleri, bu
denetimin adını (yaşam süresi) ve ne zaman yazılması gerektiğini verdi; üçüncü konusu tekliği
aşıp sahipliği sayılabilir, paylaşılabilir ve en sonunda değiştirilebilir hâle getirdi — ama
her adımda bitiş noktası hâlâ belirlenimciydi, ta ki bu derste iki değerin birbirini tuttuğu
görülene kadar.

Kursun on üç dersi boyunca bir kavram yalnızca adıyla geçti ve tanımlanmadan bırakıldı: `Drop`
trait'i. Kapanış (closure) ve yineleyici (iterator) bu kursta hiç geçmedi; üçü de aynı soruyu
paylaşıyor — bir değerin **ne** yapabildiği, ne kadar yaşadığından ayrı bir soru — ve sıradaki
kurs tam bu soruyu açıyor.

