---
title: Numaralandırmalar
source: 'https://academia.sh/tr/kurslar/rust-temelleri/numaralandirmalar'
course: 'Rust Temelleri'
language: tr
updated: '2026-09-13T05:09:29+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Bir varyant kurmanın ifade, enum bildiriminin öğe olduğunu gösterir'
    - 'Veri taşıyan ve taşımayan varyantların aynı tip altında sayıldığını açıklar'
    - 'Varyant sayısı ile bir değerin taşıyabileceği durum sayısı arasındaki farkı örnekle ayırt eder'
---

# Numaralandırmalar

Bir Sekil değeri üç ayrı biçimde kurulabiliyor — hiç veri taşımadan, tek bir sayı taşıyarak, iki sayı taşıyarak — ve üçü de aynı tip altında sayılıyor; varyant kurmak bir ifade, enum bildiriminin kendisi bir öğe. Sınırlayıcı ölçüm varyant sayısının durum sayısıyla karıştırılmaması gerektiğini gösteriyor.

Yapılar dersi, bir `Nokta`nın her zaman hem `x` hem `y` taşıdığını ölçtü: yapı, sabit bir
alan kümesine bağlı, tek bir biçime sahip bir değerdir. Ama bir programın modellemesi
gereken veri çoğu zaman "ya şu ya bu" biçiminde birden fazla olası şekle bürünür — bir
şeklin hiç çizilmemiş olması, bir çember olması ya da bir dikdörtgen olması gibi. Yapı
bunu tek başına karşılayamaz; bu dersin konusu olan numaralandırma (enum), tam bu boşluğu
dolduruyor.

Bir numaralandırma, bir değerin aynı tip altında birden fazla ayrı **varyanttan** birini
taşıyabilmesini kurar. Önceki dersle aynı soru burada da geçerli: bir varyant kurmak
çalıştırıldığında bir değer mi üretiyor, yoksa `enum` bildiriminin kendisi mi bir şey
üretiyor? Yanıt yapılarla aynı düzendedir, ama bu kez alan sayısı değil **varyant sayısı**
ile bir değerin taşıyabileceği durum sayısı arasındaki fark da ölçülüyor.

Bir numaralandırmayı, aynı işlevi görmeyen bir sabitler kümesinden ayıran şey, her
varyantın isteğe bağlı olarak kendi verisini taşıyabilmesidir. Ayrı ayrı tanımlanmış üç
sabit — `BOS`, `CEMBER`, `DIKDORTGEN` gibi — birbirinden bağımsız üç addır; aralarında
"hangisi seçili" sorusuna derleyicinin garanti verdiği bir yanıt yoktur. Bir `enum` ise
tek bir tip kurar ve o tipin her değeri, o an hangi varyantı taşıdığını kendi içinde bilir.
Bu dersin ölçtüğü ilk şey, bu tek tipliğin öğe/ifade ekseninde nasıl göründüğüdür.

## Bildirim Yine Bir Öğedir, Varyant Kurmak Bir İfadedir

`enum Sekil { Bos, Cember(f64), Dikdortgen(f64, f64) }` satırı, tıpkı bir önceki dersteki
`struct` bildirimi gibi, çalıştırıldığında hiçbir şey üretmez. Bu satır derleyiciye üç ayrı
varyantı olan bir tip tanıtır; kendisi bir öğedir. Buna karşılık `Sekil::Cember(2.0)`
yazımı çalıştırıldığında bir değer üretir — bir tam sayı yerine, `Cember` varyantını taşıyan
ve içinde `2.0`ı barındıran bir `Sekil` değeri. Bu bir ifadedir; sonucu bir değişkene
bağlanabilir, bir listeye eklenebilir, bir fonksiyona geçirilebilir.

**RV5.** — "`enum` bildiriminin tek başına hiçbir şey üretmediği" iddiası, tıpkı bir önceki
dersteki `struct` örneğinde olduğu gibi, ayrı bir koşumla değil aşağıdaki programın
yapısıyla doğrulanıyor: `enum Sekil { ... }` satırı `main`den önce duruyor ve hiçbir
yazdırma çağrısı doğrudan o satırı tetiklemiyor; görünen her çıktı, varyantların
**kurulduğu** ve **kullanıldığı** satırlardan geliyor.

`Bos`, `Cember` ve `Dikdortgen` üç ayrı varyant adıdır ve üçü de tek bir `enum Sekil { }`
bildirimi içinde, virgülle ayrılarak sıralanır. `Cember(f64)` ile `Dikdortgen(f64, f64)`
arasındaki fark parantez içindeki tip sayısıdır: biri tek bir `f64` taşır, öbürü iki
`f64` taşır; `Bos`un parantezi bile yoktur, çünkü hiç veri taşımaz. Bu üç biçim — parantezsiz,
tek alanlı, çok alanlı — bir `enum` bildiriminin izin verdiği bütün varyant türlerini
kapsıyor.

Aşağıdaki koşum, `Sekil` tipinden dört değer kurup her birinin hangi varyanta ait olduğunu
ve alanı ne kadar olduğunu basıyor.

```rust
// sekil_enum.rs — enum bildirimi bir oge, varyant kurmak bir ifadedir
use std::collections::BTreeSet;

enum Sekil {
    Bos,
    Cember(f64),
    Dikdortgen(f64, f64),
}

fn varyant_adi(s: &Sekil) -> &'static str {
    match s {
        Sekil::Bos => "Bos",
        Sekil::Cember(_) => "Cember",
        Sekil::Dikdortgen(_, _) => "Dikdortgen",
    }
}

fn alan(s: &Sekil) -> f64 {
    match s {
        Sekil::Bos => 0.0,
        Sekil::Cember(yaricap) => std::f64::consts::PI * yaricap * yaricap,
        Sekil::Dikdortgen(genislik, yukseklik) => genislik * yukseklik,
    }
}

fn main() {
    let liste = vec![
        Sekil::Bos,
        Sekil::Cember(2.0),
        Sekil::Cember(5.0),
        Sekil::Dikdortgen(3.0, 4.0),
    ];

    println!("{:<20}: {}", "tasinan deger sayisi", liste.len());
    for (i, s) in liste.iter().enumerate() {
        println!(
            "{:<20}: {:<11} alan={:.2}",
            format!("liste[{}] varyanti", i),
            varyant_adi(s),
            alan(s)
        );
    }

    let ayri_varyantlar: BTreeSet<&str> = liste.iter().map(varyant_adi).collect();
    println!("{:<20}: {}", "ayri varyant sayisi", ayri_varyantlar.len());
}
```

```
tasinan deger sayisi: 4
liste[0] varyanti   : Bos         alan=0.00
liste[1] varyanti   : Cember      alan=12.57
liste[2] varyanti   : Cember      alan=78.54
liste[3] varyanti   : Dikdortgen  alan=12.00
ayri varyant sayisi : 3
```

`liste`, dört ayrı çağrıyla kuruldu ve her çağrı bir ifadeydi: `Sekil::Bos`, hiç veri
taşımadan bile bir `Sekil` değeridir; `Sekil::Cember(2.0)` bir ondalık sayı taşıyarak,
`Sekil::Dikdortgen(3.0, 4.0)` iki ondalık sayı taşıyarak aynı sonuca varır. Üçü de
`Vec<Sekil>` içine `push` edilebildi — derleyici için hepsi aynı tip, `Sekil`.

`varyant_adi` ve `alan` fonksiyonları burada bir araç olarak kullanılıyor: her ikisi de
`match` ile bir değerin hangi varyantı taşıdığını okuyor ve varyanta özgü bir sonuç
üretiyor. `match`in kendi kuralları ve dalların bütünlüğü sıradaki dersin konusu; burada
yalnızca veri taşıyan bir varyanttan (`Cember`, `Dikdortgen`) o veriye ulaşmanın bir yol
gerektirdiği görülüyor — veri taşımayan `Bos` varyantından ise okunacak bir alan yok, `alan`
fonksiyonu onun için doğrudan `0.0` veriyor.

`alan` fonksiyonunun verdiği sayılar bunu somutlaştırıyor: `Cember(2.0)`nin alanı
$\pi \times 2^2 \approx 12{,}57$, `Cember(5.0)`in alanı $\pi \times 5^2 \approx 78{,}54$.
İkisi de aynı formülü kullanıyor — yarıçapın karesiyle pi sayısının çarpımı — ama taşınan
sayı farklı olduğu için sonuç da farklı.
`Dikdortgen(3.0, 4.0)`ün alanı ise `12.00`; bu varyant tek bir sayı değil iki sayı taşıyor
ve `alan` fonksiyonu ikisini de okuyup çarpıyor. `Bos` varyantı hiçbir sayı taşımadığından,
onun için hesaplanacak bir alan yok — `alan` bu durumu ayrı bir dalda `0.0` ile karşılıyor.

Varyant adlarını saymak için burada karma küme değil sıralı küme (`BTreeSet`) kullanıldı,
oysa yalnızca `.len()` okunuyor ve bir kümenin eleman sayısı gezinme sırasından
bağımsızdır — bu tek satır için karma küme de aynı sonucu verirdi. Tercih burada bir
zorunluluktan değil, kurs boyunca sürecek bir alışkanlıktan geliyor: çıktısı koşumdan
koşuma değişmeyen bir yapı gerektiğinde sıralı yapı varsayılan seçimdir. Bu seçimin ne
zaman zorunlu, ne zaman yalnızca tutarlılık olduğu Sıralı ve Küme Yapıları dersinin
konusu.

## Veri Taşıyan ve Taşımayan Varyantlar Aynı Tipte Sayılır

`Sekil` tipinin üç varyantından biri (`Bos`) hiç veri taşımıyor, ikisi (`Cember`,
`Dikdortgen`) taşıyor. Yukarıdaki koşumda `liste.len()` dördü de saydı; `Sekil` tipi
hepsini eşit ağırlıkta tutuyor. Bu, Rust'ın numaralandırmasını bir listeden ("hangi
seçenek?") ayıran temel özelliktir: yalnızca bir ad değil, isteğe bağlı olarak bir de
**yük** taşıyabilir. Veri taşımayan bir varyant, veri taşıyanın yükü sıfır olan özel bir
durumu değildir — ikisi de aynı `enum` bildiriminin eşit değerli birer üyesidir.

Bu eşitlik `Vec<Sekil>` gibi bir koleksiyonun neden mümkün olduğunu da açıklıyor. Bir
koleksiyon tek bir tip taşır; eğer `Bos`, `Cember` ve `Dikdortgen` üç ayrı tip olsaydı,
üçünü aynı listede tutmak mümkün olmazdı. `enum` bunu tek bir tip altında birleştirerek
çözüyor: `Sekil` değişkeninin taşıdığı asıl varyant çalışma zamanında bellekte saklanıyor,
ama derleme zamanında `Sekil` tek bir tip olarak görülüyor.

**RV6.** — "Veri taşıyan ve taşımayan varyantların aynı tipte sayıldığı" iddiası burada
`Vec<Sekil>` içine dördünün birden konabilmesiyle ölçülüyor: eğer varyantlar farklı
tiplerde sayılsaydı, derleyici `liste` içindeki dördüncü öğeyi (`Dikdortgen`) ilkinden
(`Bos`) farklı bir tip olarak reddederdi. Derlemenin sorunsuz geçmesi, `tasinan deger
sayisi: 4` satırının dördünü de saymasıyla birlikte bu eşitliğin doğrudan kanıtıdır.

Varyant adları tek başlarına değil, tip adıyla birlikte yazılır: `Sekil::Cember(2.0)`,
`Cember(2.0)` değil. Bu öneki gerektiren şey, aynı adın birden fazla `enum`da varyant
olarak kullanılabilmesidir — başka bir tipte de `Cember` adında bir varyant tanımlanmış
olsaydı, `Sekil::` öneki olmadan hangi tipin `Cember`inden söz edildiği belirsiz kalırdı.
Bu, bir yapı değerinin kurulmasından (`Nokta { x: 3, y: 4 }`) farklı bir noktadır: yapı
kurma sözdiziminde tip adı zaten baştadır ve tekrar bir öneke gerek kalmaz, ama bir varyant
kurma sözdiziminde tip adı ile varyant adı iki ayrı ad olduğundan aralarına `::` konur.

Bu tek tiplilik, her `Sekil` değerinin hangi varyantı taşıdığını kendi içinde bilmesiyle
mümkün olur: `varyant_adi` fonksiyonu tam olarak bu bilgiyi okuyor; `alan` fonksiyonu ise
hem hangi varyant olduğunu okuyor hem de ona göre farklı alanlara erişiyor. Bir yapıda
böyle bir ayrım yoktur, çünkü bir yapının bütün alanları her zaman aynı andadır — `Nokta`
değeri hiçbir zaman "şu an yalnızca `x`i var" durumuna düşmez. `enum` bunu tersine çevirir:
bir değer, aynı anda yalnızca **bir** varyantın alanlarına sahiptir, diğer varyantların
alanları o değer için hiç yoktur.

Bu, `Sekil::Dikdortgen(3.0, 4.0)` değerinin aynı zamanda bir `yaricap` alanı da taşıdığı
anlamına gelmez — o değer yalnızca `genislik` ve `yukseklik` taşır, `Cember` varyantının
alanı ondan tamamen ayrıdır. `alan` fonksiyonunun `match` ifadesindeki her dal, yalnızca
kendi varyantının alanlarına erişebilir; `Sekil::Cember(yaricap) => ...` dalında `genislik`
adına erişmek mümkün değildir, çünkü o dal yalnızca `Cember` varyantı eşleştiğinde
çalışır ve o anda ortada bir `genislik` yoktur.

Bu, bellekte kaç baytın ayrıldığı sorusuna değinmez — ders böyle bir sayı basmıyor —
yalnızca hangi alanların hangi durumda **erişilebilir** olduğunu ölçüyor. Erişilebilirlik,
`match`in dal yapısıyla dile getirilen bir kaynak-düzeyi kuraldır: bir dalın içine yalnızca
o dalın eşleştiği varyantın alanları girer.

## Sınırlayıcı Ölçüm: Varyant Sayısı Durum Sayısı Değildir

`Sekil` üç varyant taşıyor: `Bos`, `Cember`, `Dikdortgen`. Ama "üç varyant" ile "üç olası
değer" aynı şey değildir. `Bos`un taşıyabileceği tek bir durum vardır — kendisi. `Cember`
ise bir `f64` taşıyor ve bir `f64`ün alabileceği değer sayısı sayılamayacak kadar
büyüktür. Aynı varyant, farklı yarıçaplarla, sonsuz sayıda farklı **durum** üretebilir.

```rust
// ayni_varyant_farkli_durum.rs — varyant sayisi durum sayisi degildir
enum Sekil {
    Cember(f64),
}

fn main() {
    let kucuk = Sekil::Cember(2.0);
    let buyuk = Sekil::Cember(5.0);

    let Sekil::Cember(r1) = &kucuk;
    let Sekil::Cember(r2) = &buyuk;

    println!("{:<24}: {}", "kucuk cember yaricapi", r1);
    println!("{:<24}: {}", "buyuk cember yaricapi", r2);
    println!("{:<24}: {}", "ayni varyant mi", true);
    println!("{:<24}: {}", "ayni durum mu", r1 == r2);
}
```

```
kucuk cember yaricapi   : 2
buyuk cember yaricapi   : 5
ayni varyant mi         : true
ayni durum mu           : false
```

`kucuk` ile `buyuk`, ikisi de `Cember` varyantını taşıyor — "ayni varyant mi" sorusunun
yanıtı `true`. Ama ikisi aynı durumu taşımıyor: biri `2.0` yarıçaplı, öbürü `5.0` yarıçaplı
— "ayni durum mu" sorusunun yanıtı `false`. Bir önceki koşumda ölçülen "üç ayrı varyant"
sayısı, `Cember` gibi veri taşıyan bir varyantın kaç farklı **durumda** görünebileceğini
söylemiyor.

**RV7.** — Bu sınırlayıcı ölçüm, tek bir kod bloğunda iki ayrı `Sekil::Cember` değeri
kurup ikisinin de aynı varyanttan geldiğini (`true`) ama farklı bir yarıçap taşıdığını
(`r1 == r2` sonucu `false`) yan yana basarak ölçülüyor. "Varyant sayısı" kaynaktan
`enum` bildirimini okuyarak (üç satır, üç varyant) bulunabilirken, "durum sayısı" ancak
programın çalışması sırasında hangi değerlerin üretildiğine bakılarak bulunabilir; ikisi
farklı sorulara yanıt veriyor.

Bu ayrım, veri taşımayan bir varyant için ortadan kalkar. `Bos`un tek bir durumu vardır,
çünkü hiçbir alan taşımaz — varyant sayısı ile durum sayısı orada çakışır. Fark yalnızca
veri taşıyan varyantlarda açılır ve açıldığı andan itibaren durum sayısı taşınan verinin
tipine bağlı hâle gelir: bir `bool` taşıyan bir varyantın iki durumu olur, bir `f64`
taşıyan bir varyantın ise pratikte sınırsız durumu olur.

Bu, tek alanlı bir varyant için bile geçerlidir; alan sayısı arttıkça durum sayısı çarpımsal
büyür. `Dikdortgen(f64, f64)` iki ayrı `f64` taşıyor — genişlik ve yükseklik birbirinden
bağımsız değişebiliyor, bu yüzden bu tek varyantın durum uzayı, bir boyutlu değil iki
boyutlu bir sonsuzluktur. Yukarıdaki koşumda yalnızca `Dikdortgen(3.0, 4.0)` görüldü, ama
kaynakta yazan `Dikdortgen(f64, f64)` bildirimi bundan çok daha fazlasına izin veriyor:
`Dikdortgen(1.0, 1.0)`, `Dikdortgen(0.5, 100.0)` ve sayılamayacak kadar başka çift, hepsi
aynı varyanta ait ama hiçbiri aynı durumu paylaşmıyor.

Bu yüzden "kaç durum" sorusunun yanıtı, `enum` bildirimine bakılarak değil, o bildirimin
alanlarındaki tiplere bakılarak verilir. Veri taşımayan bir varyant durum sayısına tam
olarak `1` katar; sabit sayıda ayrı değer alabilen bir tip taşıyan bir varyant (örneğin
kendisi de sınırlı sayıda varyantı olan başka bir `enum`) o tipin durum sayısı kadar katkı
yapar; `f64` ya da `String` gibi sınırsız bir tip taşıyan bir varyant ise durum sayısını
sınırsız yapar. Kaynaktaki üç satırlık `enum Sekil { ... }` bildirimi bu farkı hiçbir
yerde göstermiyor — üçü de aynı biçimde, birer varyant adı olarak yazılıyor.

Bu ayrımın pratik bir sonucu var: bir `Sekil` değerini ele alan bir kodun doğruluğu,
"üç varyantın hepsi ele alındı mı" sorusuyla ölçülür — "sonsuz durumun hepsi test edildi
mi" sorusuyla değil. `alan` fonksiyonu `Cember(2.0)` için doğru sonucu veriyorsa,
`Cember(5.0)` için de aynı yoldan doğru sonucu verir, çünkü ikisi aynı dalda işleniyor;
tek tek her yarıçapı sınamaya gerek yoktur. Derleyicinin bütünlük denetimi de tam olarak
varyant düzeyinde çalışır, durum düzeyinde değil — bu sınır sıradaki dersin ölçtüğü
"bütünlük" kavramının neye garanti verip neye vermediğini de önceden belirliyor.

Bu ders, bir `Sekil` değerinin kaç ayrı biçim alabileceğini ve bu biçimlerin kaynakta nasıl
kurulduğunu ölçtü. Ama bir değeri kurmak bir yarısı; kurulan değerin hangi varyantı
taşıdığını **okumak** öbür yarısıdır ve bu ders o okumayı yalnızca iki yardımcı
fonksiyonun (`varyant_adi`, `alan`) içinde, arka planda kullandı. `match`in kendisi —
hangi desen biçimlerinin var olduğu, bir dalın ne zaman diğerinden önce geldiği, derleyicinin
neden bütün varyantların ele alınmasını istediği — hiç açılmadı.

## Özet

- `enum` bildirimi bir öğedir: çalıştırıldığında hiçbir değer üretmez, yalnızca varyantları
  tanımlar.
- Bir varyant kurmak (`Sekil::Cember(2.0)` gibi) bir ifadedir ve bir değer üretir.
- Veri taşıyan ve taşımayan varyantlar aynı `enum` tipi altında eşit ağırlıkta sayılır; bu
  sayede tek bir koleksiyon (`Vec<Sekil>` gibi) hepsini birlikte tutabilir.
- Varyant sayısı, kaynaktaki `enum` bildiriminden okunan sabit bir sayıdır.
- Durum sayısı bundan farklıdır: veri taşıyan bir varyant, taşıdığı verinin tipine bağlı
  olarak bir, birkaç ya da sayılamayacak kadar çok durum üretebilir.

## Sonraki Adım

Bu ders, bir `Sekil` değerinin kaç ayrı varyant taşıyabileceğini ve varyant kurmanın nasıl
bir ifade olduğunu ölçtü; `varyant_adi` ve `alan` fonksiyonları bu varyantları ayırt etmek
için `match` kullandı ama `match`in kendi kurallarına girmedi. Sıradaki ders tam bu
boşluğu dolduruyor: bir `Sekil` değerinin hangi varyantı taşıdığı kaynakta nasıl okunuyor,
kaç ayrı desen biçimi bunu yapabiliyor ve derleyici bütün varyantların ele alınmasını
neden istiyor?
