---
title: Dizileştirme
source: 'https://academia.sh/tr/kurslar/rust-soyutlama/dizilestirme'
course: "Trait'ler, Genellikler ve Hata Yönetimi"
language: tr
updated: '2026-10-21T05:03:45+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Bir yapının alanlarına uygulanan dönüşüm gövdesinin alan başına kaç kez koştuğunu ve iç içe bir yapıda bu sayının nasıl büyüdüğünü koşturarak gösterir'
    - 'Metinden yapıya çözümlemede bir alanın başarısızlığının sonraki alanların gövdesini hiç çalıştırmadığını ölçerek doğrular'
    - 'Kursun on beş dersinde ölçülen bütün gövdeleri sınıflarına göre bir kapanış tablosunda karşılaştırır'
---

# Dizileştirme

Bir yapının alanlarına elle yazılmış bir dönüşüm gövdesi uygulanırken bu gövdenin alan başına kaç kez koştuğunun, iç içe bir yapıda bu sayının nasıl çarpımsal büyüdüğünün ve ters yönde — metinden yapıya — bir alanın başarısızlığının sonraki alanların gövdesini hiç çalıştırmadığının ölçülmesi; kursun on beş dersinde ölçülen bütün gövdeler burada tek bir tabloda toplanıyor.

Yineleyici Bağdaştırıcıları dersi, bir zincirin ucundaki tüketicinin kaynaktaki bir dönüşüm
gövdesini kaç kez çağırdığını ölçtü — zincirin uzunluğu sabit kalırken koşan gövde sayısı
tüketiciye göre değişiyordu. Bu kapanış dersi aynı soruyu somut bir veri biçimine taşıyor: bir
yapının alanlarına uygulanan bir dönüşüm gövdesi, yapı serilirken alan başına kaç kez koşuyor.
Burada zincirin elemanları artık bir dizinin girdileri değil, tek bir yapının alanları; tüketici
de tektir — serileştirmenin kendisi. Dönüşüm bu derste elle yazılıyor, üçüncü taraf bir kasa
kullanılmıyor; bir dizileştirme çerçevesi olsaydı bu gövdeyi kendisi üretirdi, ama burada gövde
kaynakta görünür kalıyor ve sayılabiliyor. Kurs boyunca sorulan soru burada da değişmiyor:
kaynakta yazdığın bu gövde kaç kez koştu? Bu, kursun on beşinci ve son dersi; kapanışında on
dört dersin tamamında ölçülen gövdeler tek bir tabloda toplanacak.

## Alan Başına Koşan Dönüşüm Gövdesi

Bir dizileştirme çerçevesi olsaydı bu dönüşümü kendisi üretir, alan sayısı arttıkça gövdeyi
görünmez biçimde büyütürdü. Bu ders dönüşümü elle yazıyor: her alan, aynı yardımcı işlevden
geçerek bir dizgeye çevriliyor ve bu geçiş her seferinde sayaç defterine bir kayıt düşüyor.
Ölçüm çekirdeğinin bu kesiti yalnız sayma defterini taşıyor; trait, sınır ya da hata tipi bu
derste kullanılmıyor.

```rust
// kere.rs — kesit: sayma defteri.

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

pub type Defter = Rc<RefCell<BTreeMap<String, u32>>>;

pub fn say(defter: &Defter, ad: &str) {
    *defter.borrow_mut().entry(ad.to_string()).or_insert(0) += 1;
}

pub fn kere(defter: &Defter, ad: &str) -> u32 {
    *defter.borrow().get(ad).unwrap_or(&0)
}
```

Üç alanlı bir `Nokta` yapısı, alanlarını sırayla dizgeye çeviren bir `dizilestir` yöntemi
taşıyor; her alan aynı `alani_yaz` işlevinden geçiyor ve geçiş sayılıyor. `Cizgi`, iki `Nokta`yı
birden taşıyan bir yapı; kendi `dizilestir`i kendi alanına dokunmuyor, taşıdığı iki `Nokta`nın
`dizilestir`ini çağırıyor. `Ucgen`, üç `Cizgi`yi taşıyan bir yapı; aynı örüntü bir kat daha
derine iniyor.

```rust
// alan-govdesi.rs — bir govdenin alan basina kac kez kostugunu olcer, ic ice buyumeyi gosterir.
mod kere;
use kere::{kere, say, Defter};
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::rc::Rc;

fn alani_yaz(defter: &Defter, ad: &str, deger: i32) -> String {
    say(defter, "alan-govdesi");
    format!("{}={}", ad, deger)
}

struct Nokta {
    x: i32,
    y: i32,
    z: i32,
}

impl Nokta {
    fn dizilestir(&self, defter: &Defter) -> String {
        let x = alani_yaz(defter, "x", self.x);
        let y = alani_yaz(defter, "y", self.y);
        let z = alani_yaz(defter, "z", self.z);
        format!("{};{};{}", x, y, z)
    }
}

struct Cizgi {
    bas: Nokta,
    bitis: Nokta,
}

impl Cizgi {
    fn dizilestir(&self, defter: &Defter) -> String {
        format!("{}|{}", self.bas.dizilestir(defter), self.bitis.dizilestir(defter))
    }
}

struct Ucgen {
    kenar1: Cizgi,
    kenar2: Cizgi,
    kenar3: Cizgi,
}

impl Ucgen {
    fn dizilestir(&self, defter: &Defter) -> String {
        format!(
            "{}#{}#{}",
            self.kenar1.dizilestir(defter),
            self.kenar2.dizilestir(defter),
            self.kenar3.dizilestir(defter)
        )
    }
}

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

    let onceki = kere(&defter, "alan-govdesi");
    let nokta = Nokta { x: 1, y: 2, z: 3 };
    let _ = nokta.dizilestir(&defter);
    let sonraki = kere(&defter, "alan-govdesi");
    println!("Nokta (3 alan): {} govde kosumu", sonraki - onceki);

    let onceki = sonraki;
    let cizgi = Cizgi {
        bas: Nokta { x: 0, y: 0, z: 0 },
        bitis: Nokta { x: 5, y: 5, z: 5 },
    };
    let _ = cizgi.dizilestir(&defter);
    let sonraki = kere(&defter, "alan-govdesi");
    println!("Cizgi (2 nokta, 6 alan): {} govde kosumu", sonraki - onceki);

    let onceki = sonraki;
    let ucgen = Ucgen {
        kenar1: Cizgi {
            bas: Nokta { x: 0, y: 0, z: 0 },
            bitis: Nokta { x: 1, y: 1, z: 1 },
        },
        kenar2: Cizgi {
            bas: Nokta { x: 1, y: 1, z: 1 },
            bitis: Nokta { x: 2, y: 2, z: 2 },
        },
        kenar3: Cizgi {
            bas: Nokta { x: 2, y: 2, z: 2 },
            bitis: Nokta { x: 0, y: 0, z: 0 },
        },
    };
    let _ = ucgen.dizilestir(&defter);
    let sonraki = kere(&defter, "alan-govdesi");
    println!("Ucgen (3 cizgi, 18 alan): {} govde kosumu", sonraki - onceki);

    println!("toplam alan-govdesi kosumu: {}", kere(&defter, "alan-govdesi"));
}
```

```
Nokta (3 alan): 3 govde kosumu
Cizgi (2 nokta, 6 alan): 6 govde kosumu
Ucgen (3 cizgi, 18 alan): 18 govde kosumu
toplam alan-govdesi kosumu: 27
```

**YN11.** `Nokta` üç alan taşıyor ve `dizilestir`i üç kez `alan-govdesi` kaydı düşürüyor — bire
bir. `Cizgi` kendi alanına hiç dokunmuyor, yalnız iki `Nokta`nın `dizilestir`ini çağırıyor; ama
her çağrı kendi üç kaydını taşıdığı için toplam altıya çıkıyor. `Ucgen` aynı örüntüyü bir kat
daha derine taşıyor: üç `Cizgi`nin her biri altı kayıt bırakıyor, toplam on sekiz. Alan sayısı
ile gövde koşum sayısı arasındaki bağıntı burada bire birdir — ama bu bağıntı yalnız yaprak
düzeydeki asıl alanlar (`x`, `y`, `z`) için geçerli; `Cizgi` ve `Ucgen`in kendi gövdeleri hiç
`alan-govdesi` kaydı bırakmıyor, yalnız taşıdıkları alt yapılara devrediyor. İç içe geçme,
sayıyı toplamsal değil çarpımsal büyütüyor: `Ucgen`in üç kenarı, her kenarın altı kaydını
çarpıyor.

## Ters Yönde Çözümleme: Bir Alanın Başarısızlığı Sonrakini Durdurur

Aynı soru ters yönden de sorulabilir: bir dizge, alan başına kaç gövde koşturarak bir yapıya
geri çevrilir? Çözümleme de elle yazılıyor — her alan `alani_oku` adlı ortak bir işlevden
geçiyor; bu işlev önce bir kayıt düşürüyor, sonra dizge parçasını ayrıştırmayı deniyor.
`Nokta::ters_dizilestir`, üç alanı sırayla okuyor ve her okuma çağrısının ardına bir soru
işareti koyuyor — Hata Yayılımının Kısa Yazımı dersinde ölçülen erken dönüş burada da geçerli:
bir alan başarısız olursa, soru işareti kalan alanların gövdesini hiç çalıştırmadan işlevden
çıkıyor.

```rust
// gozumleme.rs — ters yon: metinden yapiya, alan basina govde kosumu.
mod kere;
use kere::{kere, say, Defter};
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::rc::Rc;

struct GozumHatasi;

struct Nokta {
    x: i32,
    y: i32,
    z: i32,
}

fn alani_oku(defter: &Defter, ad: &str, anahtar: &str, parca: &str) -> Result<i32, GozumHatasi> {
    say(defter, anahtar);
    let ikili: Vec<&str> = parca.splitn(2, '=').collect();
    if ikili.len() != 2 || ikili[0] != ad {
        return Err(GozumHatasi);
    }
    ikili[1].parse::<i32>().map_err(|_| GozumHatasi)
}

impl Nokta {
    fn ters_dizilestir(defter: &Defter, on_ek: &str, metin: &str) -> Result<Nokta, GozumHatasi> {
        let parcalar: Vec<&str> = metin.split(';').collect();
        if parcalar.len() != 3 {
            return Err(GozumHatasi);
        }
        let x = alani_oku(defter, "x", &format!("{}-x", on_ek), parcalar[0])?;
        let y = alani_oku(defter, "y", &format!("{}-y", on_ek), parcalar[1])?;
        let z = alani_oku(defter, "z", &format!("{}-z", on_ek), parcalar[2])?;
        Ok(Nokta { x, y, z })
    }
}

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

    let gecerli = Nokta::ters_dizilestir(&defter, "gecerli", "x=1;y=2;z=3");
    if let Ok(n) = &gecerli {
        println!("gecerli metin cozumlendi: x={} y={} z={}", n.x, n.y, n.z);
    }
    println!(
        "gecerli-x: {}  gecerli-y: {}  gecerli-z: {}",
        kere(&defter, "gecerli-x"),
        kere(&defter, "gecerli-y"),
        kere(&defter, "gecerli-z")
    );

    let gecersiz = Nokta::ters_dizilestir(&defter, "gecersiz", "x=1;y=degil;z=3");
    println!("gecersiz metin basarili mi: {}", gecersiz.is_ok());
    println!(
        "gecersiz-x: {}  gecersiz-y: {}  gecersiz-z: {}",
        kere(&defter, "gecersiz-x"),
        kere(&defter, "gecersiz-y"),
        kere(&defter, "gecersiz-z")
    );
}
```

```
gecerli metin cozumlendi: x=1 y=2 z=3
gecerli-x: 1  gecerli-y: 1  gecerli-z: 1
gecersiz metin basarili mi: false
gecersiz-x: 1  gecersiz-y: 1  gecersiz-z: 0
```

**YN12.** Geçerli dizgede (`x=1;y=2;z=3`) üç alan da okunuyor ve üç ayrı sayaç birer kez
artıyor — ileri yöndeki bire bir bağıntı burada da geçerli. Geçersiz dizgede (`x=1;y=degil;z=3`)
`x` alanı okunuyor ve başarılı oluyor, `y` alanı da okunuyor ama sayısal olarak ayrıştırılamıyor
— ikisinin de sayacı birer artıyor, çünkü ikisi de en azından denendi. `z` alanının sayacı
sıfırda kalıyor: soru işareti `y`nin başarısızlığını yakaladığı anda işlevden çıkıyor, `z` için
yazılan gövdeye hiç uğranmıyor. Bu, ileri yöndeki her seferinde sınıfının ters yönde koşulsuz
kalmadığını gösteriyor: bir alanın gövdesi, kendisinden önceki alanların başarısına bağlı hale
geliyor.

## Sınırlayıcı Ölçüm

Alan sayısı ile gövde koşum sayısı arasındaki bire bir bağıntı, bu derste kullanılan
yapıların hepsi koşulsuz alanlar taşıdığı için geçerli — her alan her zaman var, her zaman
dönüştürülüyor. Yokluğun Tiple İfadesi dersinde ölçülen yokluk tipi bir alanın kendisi
olsaydı, o alanın dönüşüm gövdesi artık koşulsuz çalışmazdı: bazı değerlerde koşar, bazılarında
hiç koşmazdı ve alan sayısını saymak tek başına gövde koşum sayısını vermezdi. Bu ders bu
durumu koşturmuyor; yalnız bağıntının hangi koşulda geçerli olduğunu, hangi koşulda
bozulacağını söylüyor.

İkinci bir sınır, sayının neyi ölçmediğiyle ilgili. `alan-govdesi` sayacı yalnız gövdenin kaç
kez çağrıldığını sayıyor — ürettiği dizgenin ne kadar uzun olduğunu, ya da bir alanın
dönüşümünün ne kadar pahalı olduğunu ölçmüyor. Tek bir tamsayı alanı ile büyük bir koleksiyon
taşıyan bir alan, bu sayaç için aynı — ikisi de bir kez sayılıyor. Kursun başından beri
sürdürülen bu ayrım burada da geçerli: sayı yalnız kaç kez çalıştığını gösteriyor, ne kadar
sürdüğünü ya da ne ürettiğini değil.

## Kapanış Tablosu

| Ders | Ölçülen gövde | Sınıfı | Sınırlayıcı ölçüm |
|---|---|---|---|
| Trait Tanımı ve Gerçekleştirimi | Varsayılan trait gövdesi (`ad`) | her seferinde · hiç | Sıfır koşum, gövdenin kaynakta yok olduğu anlamına gelmez |
| Trait Sınırları | Sınırlı ve sınırsız gövdenin koşum sayısı | her seferinde | Bedel derlemede: her tip için ayrı gövde üretimi, koşumla ölçülemez |
| İlişkili Tipler | İlişkili tip / genellik parametresi çağrıları | her seferinde | Fark koşumda değil, çağıranın yazmak zorunda kaldığı bilgide |
| Nesne Güvenliği ve Dinamik Gönderim | `statik-gonderim` / `dinamik-gonderim` | her seferinde | Aynı sayı aynı bedel değil; çağrının nasıl bulunduğu ölçülemez |
| Türetilen Trait'ler | Elle yazılan / türetilmiş eşitlik gövdesi | her seferinde (elle) · sayılamaz (türetilmiş) | Türetilmiş gövde kaynakta yazılı değil, koşum sayısı sayılamaz |
| İşleç Aşırı Yükleme | `islec-govdesi` (`add`) | her seferinde | Çağrı yeri kaynakta görünmez, sayı ancak koşum defteriyle bilinir |
| Yokluğun Tiple İfadesi | Hazır / tembel varsayılan gövde | her seferinde · yalnız gerektiğinde · hiç | Gövde ucuzsa iki yazımın sonucu aynı, fark yalnız sayıda kalır |
| Başarısızlığın Dönüş Değeri | Başarı / başarısızlık kolu | yalnız gerektiğinde · hiç | Kapsanmış kod ile koşmuş kod ayrı olgular |
| Hata Yayılımının Kısa Yazımı | Soru işareti sonrası gövde | yalnız gerektiğinde · hiç | Erken dönüş kalan gövdeyi sessizce atlar, yan etki de gerçekleşmez |
| Özel Hata Tipleri | Hata dönüşümü gövdesi (`From` / `map_err`) | her seferinde | Örtük dönüşüm çağıran bağlamdan bilgi alamaz, kayıp geri dönüşsüz |
| Panik ve Kurtarılamaz Hatalar | Kalan gövde (kurtarılabilir/kurtarılamaz) | her seferinde · hiç | Panik bir hata türü değil tasarım kararı; panik metni basılmadı |
| Kapanışlar | Çağrılmayan kapanış gövdesi | hiç | Kapanışın tanımlanması deftere girmeyen ayrı bir iş |
| Yineleyici Trait'i | Tüketilmeyen zincirin gövdesi | hiç | Tüketilmeyen zincir bedelsiz değil, bedel koşum sayacıyla ölçülemez |
| Yineleyici Bağdaştırıcıları | Tüketilen / erken biten zincir gövdesi | her seferinde · yalnız gerektiğinde | Sıra kaynaktan okunmaz, ancak bir kayıtla gözlemlenir |
| Dizileştirme | Alan başına dönüşüm gövdesi | her seferinde · hiç | Bağıntı yalnız her alan koşulsuzken geçerli; koşullu bir alan sınıfı değiştirir |

## Özet

- Bir yapının alanlarına uygulanan dönüşüm gövdesi alan başına bir kez koşar; n alan içeren
  bir yapıda bu gövde n kez çalışır — `Nokta`'da üç, iki `Nokta` içeren `Cizgi`'de altı, üç
  `Cizgi` içeren `Ucgen`'de on sekiz kez.
- İç içe geçmiş bir yapıda alan sayısı çarpımsal büyür (3, 6, 18) ve gövde koşum sayısı bu
  büyümeyi birebir izler.
- Bu gövde her seferinde sınıfına girer: her alan, dizileştirme her çağrıldığında kaçınılmaz
  olarak dönüştürülür.
- Ters yönde — metinden yapıya — bir alanın çözümlemesi başarısız olduğunda soru işareti geri
  kalan alanların gövdesini sessizce atlar; bu alanlar o koşumda hiç çalışmaz.
- Bir alan koşulsuz değilse (yokluk tipi taşıyorsa) bu bağıntı bozulur; alan sayısını saymak
  artık gövde koşum sayısını vermez.
- On beş ders boyunca ölçülen bütün gövdeler üç sınıfa (her seferinde, yalnız gerektiğinde,
  hiç) yerleşti; kapanış tablosu bunları tek yerde topluyor.

## Kurs Kapanışı

Bu kurs on beş ders boyunca tek bir soruyu sürekli farklı düzeneklere uyguladı: kaynakta
yazdığın bu gövde kaç kez koştu? Trait ve Genellikler konusu bu soruyu bir davranışın tipten
ayrılmasına, bir sınırın koşuma bir şey ekleyip eklemediğine, bir sözleşmenin iki farklı
yazımına, bir gönderim biçiminin derleme zamanı mı koşum zamanı mı çözüldüğüne, bir gövdenin
kaynakta hiç yazılı olmadan da koşabileceğine ve bir işlecin arkasında saklı bir çağrıya sordu.
Hata Yönetimi konusu aynı soruyu bir yedek değere, bir başarı/başarısızlık koluna, bir kısa
yazımın arkasındaki dallanmaya, bir hata dönüşümüne ve bir kurtarılamaz duruma taşıdı.
Kapanışlar ve Yineleyiciler konusu ve bu son ders, aynı soruyu bir tanımın kendisine, bir
dolaşım sözleşmesine, bir zincirin ucundaki tüketiciye ve şimdi bir yapının alanlarına
uyguladı. On altı gövdelik ölçüm çekirdeğinin sekizi her seferinde, üçü yalnız gerektiğinde,
beşi hiç koşmadı — bu sayı kurs boyunca değişmedi, yalnız hangi düzeneğin bu sınıflara girdiği
değişti.

Eşzamanlılık ve Asenkron Rust kursu bu soruyu bırakmıyor, öznesini değiştiriyor: bir gövdenin
kaç kez koştuğu yerine, bir işin **ilerlemek için neye ihtiyaç duyduğu** sorulacak — kendi
başına mı ilerliyor, bir yoklayıcı mı ilerletiyor, bir başkasının bitmesini mi bekliyor, yoksa
hiç mi ilerlemiyor. Nesneye Dayalı Java kursunun kararı hangi tipin verdiği sorusunun ve
Arayüzler, Hatalar ve Genellikler kursunun bağın nerede kurulduğu sorusunun yanına, bu kurs kaç
kez koştu sorusunu ekledi; sıradaki kurs bu üçlüye ilerlemek için neye ihtiyaç duyulduğu
sorusunu ekleyecek.
