---
title: 'İsteğe Bağlı Değerler'
source: 'https://academia.sh/tr/kurslar/swift/istege-bagli-degerler'
course: 'Swift Dili'
language: tr
updated: '2026-10-21T05:03:13+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'İsteğe bağlı değerin bir numaralandırma olduğunu ve değerle aynı tip olmadığını gösterir'
    - 'nil üzerinde map çağrısında dönüştürücü kapanışın hiç değerlendirilmediğini ölçer'
    - 'map ile flatMap arasındaki katman farkını çıktıdan okur'
    - 'İç içe katmanlarda dış katmanın dolu olmasının dönüştürücüyü çalıştırdığını ölçer'
---

# İsteğe Bağlı Değerler

Yokluğun tipte ifade edilmesinin, nil üzerinde dönüştürücü kapanışın hiç çalışmamasının ve iç içe katmanlarda yokluğun nerede durduğunun ölçümü.

Önceki ders kapanışları ve yakalama listesini ölçtü. Bir kapanışın gövdesi yazıldığı yerde değil, çağrıldığı yerde koşar; hiç çağrılmayan bir kapanışın gövdesi hiç değerlendirilmez. Bu ders aynı soruyu, bir kapanışı parametre olarak alan ve bazen o kapanışı hiç çağırmayan bir yöntem üzerinden sorar. O yöntem, tip sisteminin en çok kullanılan parçasına aittir: yokluğu bir değer gibi taşıyan tipe.

Çoğu dil yokluğu özel bir değerle, örneğin bir boş gösterici ya da sihirli bir sayıyla ifade eder ve o değerin her yerde kontrol edilmesini programcıya bırakır. Swift yokluğu tipin kendisine yazar. **İsteğe bağlı değer (optional)**, ya bir değer taşıyan ya da hiçbir şey taşımayan bir kutudur ve `Int?` biçiminde yazılır. `Int` her zaman bir tamsayıdır; `Int?` ise tamsayı olabilir, olmayabilir. Derleyici bu iki tipi birbirinin yerine kullandırmaz, dolayısıyla yokluğun kontrolü kendiliğinden unutulamaz; onu atlamak için zorla açmayı bilerek yazmak gerekir.

Kursun ölçü ekseni bu derste de değişmez: **bu ifade ne zaman değerlendiriliyor?** Dört an vardır: hemen, ilk kullanımda, her kullanımda, hiç. Kuralı sayan `Probe` sınıfı aşağıda olduğu gibi verilir. Bu ders eksenin dördüncü anına, yani hiç değerlendirilmeyen ifadeye odaklanır.

## Çekirdek

Her ders aynı çekirdeği kullanır. `Probe` bir ifadenin kaç kez değerlendirildiğini (`eval`) ve kaç kez kullanıldığını (`use`) sayar; `moment` özelliği bu iki sayıdan anı çıkarır. Açılış dersindeki bağlayıcı ölçümde sekiz ifadenin dağılımı 2/1/3/2 idi: ikisi hemen, biri ilk kullanımda, üçü her kullanımda, ikisi hiç. Bu derste yalnız kendi kesitini ölçeriz.

```swift
// Probe.swift — bir ifadenin ne zaman degerlendirildigini kaydeder
final class Probe {
    let label: String
    private(set) var evaluations = 0
    private(set) var uses = 0
    private var evaluatedBeforeUse = false

    init(_ label: String) {
        self.label = label
    }

    func eval<T>(_ value: T) -> T {
        evaluations += 1
        if uses == 0 { evaluatedBeforeUse = true }
        return value
    }

    func use<T>(_ access: () -> T) -> T {
        uses += 1
        return access()
    }

    var moment: String {
        if evaluations == 0 { return "hic" }
        if evaluations > 1 { return "her-kullanimda" }
        return evaluatedBeforeUse ? "hemen" : "ilk-kullanimda"
    }

    func report() {
        print("\(label): \(evaluations) degerlendirme, \(uses) kullanim -> \(moment)")
    }
}

func tally(_ probes: [Probe]) {
    for moment in ["hemen", "ilk-kullanimda", "her-kullanimda", "hic"] {
        let count = probes.filter { $0.moment == moment }.count
        print("\(moment): \(count)")
    }
}
```

## Yokluk Bir Tip Olarak

Bir isteğe bağlı değerin içinde ne olduğuna bakmadan önce kendisine bakalım. `Int("42")` bir metni tamsayıya çevirir ve çevirme başarısız olabileceği için dönüş tipi `Int?` olur. Başarılı olursa kutu doludur, `Int("x")` gibi bir çağrıda kutu boştur ve değeri `nil`'dir.

```swift
// main.swift — istege bagli deger bir numaralandirmadir
func describe(_ value: Int?) -> String {
    switch value {
    case .some(let number):
        return "dolu \(number)"
    case .none:
        return "bos"
    }
}

let parsed = Int("42")
let broken = Int("x")
print(type(of: parsed))
print(describe(parsed))
print(describe(broken))
print(parsed == .some(42), broken == .none)
print(broken == nil)
```

```
Optional<Int>
dolu 42
bos
true true
true
```

İlk satır tipin adını verir: `Int?` yalnızca bir kısaltmadır, gerçek tip `Optional<Int>`'tir. `Optional` standart kitaplıkta tanımlı bir **numaralandırmadır (enumeration)** ve iki durumu vardır: bir değer taşıyan `.some` ve hiçbir şey taşımayan `.none`. Bu yüzden `describe` işlevi kutuyu bir `switch` ile açabilir; her durum için ayrı bir kol yazılır ve `.some` kolunda taşınan değer `number` adına bağlanır. Dördüncü satır `42` değerinin `.some(42)` ile, boş kutunun `.none` ile eşit olduğunu gösterir; beşinci satır `nil` yazımının `.none` için kısaltma olduğunu gösterir.

Aynı çıktıdan ikinci bir sonuç çıkar: `Int?` ile `Int` iki ayrı tiptir. Aşağıdaki parçalar derlenmez; her ikisi de önce geçici bir ölçülen blokta koşturuldu ve derleyici ikisini de reddetti. Yazımları burada yalnızca anlatım için durur.

```swift
let a: Int? = 5
let b = a + 1   // derlenmez: Int? ile Int toplanamaz
let c: Int = nil   // derlenmez: nil yalnizca istege bagli bir tipe atanabilir
```

Birinci satırdaki toplama, kutunun içindeki sayıyı değil kutunun kendisini görür ve derleyici kutunun açılmasını ister. İkinci satırdaki atama ise `Int` tipine yokluk yazmaya çalışır. Yokluğu taşıyabilecek tek yer, tipi `?` ile işaretlenmiş olan yerdir. Kutunun nasıl açılacağı bir sonraki dersin konusudur; bu derste kutuyu açmadan onunla çalışan iki yöntemi ölçeceğiz.

## Yokluğun Kaynakları

İsteğe bağlı değerler programa yalnızca metin çevirmeyle girmez. Standart kitaplık, yokluğun olağan olduğu birçok yerde bir isteğe bağlı değer döndürür; ama her yerde değil: sınır dışındaki bir dizi indeksi `nil` vermez, programı durdurur. Bir sözlükte olmayan anahtarın değeri yoktur; boş bir dizinin ilk elemanı yoktur. Bu durumlarda özel bir hata değeri ya da bir istisna beklemek gerekmez: dönüş tipi zaten "belki" der.

```swift
// main.swift — standart kitaplik yoklugu istege bagli degerle bildirir
let ages = ["ada": 36, "alan": 41]
let names: [String] = []
print(ages["ada"], ages["grace"])
print(names.first, [3, 1, 2].first)
print(ages["ada"] == 36, ages["grace"] == nil)
```

```
Optional(36) nil
nil Optional(3)
true true
```

Birinci satırda var olan anahtarın değeri `Optional(36)` olarak gelir; yani `36` bile doğrudan bir `Int` değil, içinde `36` bulunan bir kutudur. Olmayan anahtar `nil` verir. İkinci satır aynı örüntüyü diziler için gösterir: boş dizinin `first` özelliği `nil`, dolu dizinin `first` özelliği kutulanmış bir `3` döndürür. Üçüncü satırda kutu, kutulanmamış bir sayıyla karşılaştırılır: `==` işleci, iki tarafın da `Int?` olmasını sağlayacak biçimde sağdaki `36`'yı otomatik olarak kutular. Bu yüzden `ages["ada"] == 36` derlenir; yukarıdaki `+` örneği ise kutunun içindeki değeri gerektirdiği için derlenmez.

Bu kaynaklar bir ayrımı görünür kılar: yokluğun nedeni isteğe bağlı değerin tipinde yazılı değildir. `ages["grace"]` boştur çünkü anahtar yoktur, `Int("x")` boştur çünkü metin sayı değildir, ama ikisi de aynı `nil`'dir. Neden bilgisine ihtiyaç duyulduğunda hata yönetimi devreye girer; o konu bu kursta daha sonra gelir. Yokluğun nedeni önemli olmadığında isteğe bağlı değer, en az yük getiren araçtır.

## nil Üzerinde map

`Optional` iki durumlu bir kutu olduğuna göre, kutunun içindeki değeri dönüştüren bir yöntem de iki durumda farklı davranır. `map` bir **dönüştürücü kapanış (closure)** alır. Kutu doluysa kapanış içindeki değerle çağrılır ve sonuç ayrı bir kutuya konur; kutu boşsa kapanış çağrılmaz ve sonuç boş bir kutudur. Bunu ölçelim: iki kutu, biri dolu biri boş, her biri iki kez kullanılır ve dönüştürücü kapanışın gövdesi `eval` ile işaretlenir.

```swift
// main.swift — nil uzerinde map donusturucuyu cagirmaz
let filled = Probe("map-dolu")
let vacant = Probe("map-bos")
let present: Int? = Int("21")
let missing: Int? = Int("yirmi bir")

for _ in 1...2 {
    _ = filled.use { present.map { filled.eval($0 * 2) } }
    _ = vacant.use { missing.map { vacant.eval($0 * 2) } }
}
filled.report()
vacant.report()
```

```
map-dolu: 2 degerlendirme, 2 kullanim -> her-kullanimda
map-bos: 0 degerlendirme, 2 kullanim -> hic
```

Dolu kutuda `map` her çağrıldığında dönüştürücüyü yeniden koşturur: iki kullanım, iki değerlendirme, an **her kullanımda**. Sonucun bir yerde saklanmadığına dikkat edin; `use` içindeki ifade her seferinde baştan çalışır. Boş kutuda iki kullanım vardır ama değerlendirme yoktur, çünkü `map` kutunun boş olduğunu görür görmez dönüştürücüye uğramadan döner. Gövdede yazılı `filled.eval($0 * 2)` ya da `vacant.eval($0 * 2)` ifadesi kaynakta durur, fakat boş kutuda hiçbir zaman değerlendirilmez. Kural bu durumu **hiç** diye adlandırır.

Bu ölçüm, kapanışın gövdesinin ne zaman koştuğunu bir kez daha gösterir: kapanış yazıldığı yerde koşmaz, ve onu çağırması beklenen yöntem de onu her zaman çağırmaz. Hiç çağrılmayan bir dönüştürücünün içindeki bir hata, bir yan etki ya da pahalı bir hesap hiçbir zaman gerçekleşmez. Dönüştürücünün yan etkisine güvenen bir kod, boş kutuda o yan etkiyi kaçırır.

**TS1.** Bu ölçüm yalnız `map` için; `filter`, `compactMap` ya da `forEach` gibi başka yöntemlerin boş kutudaki davranışı denenmedi. Dönüştürücünün yan etkiyle değil saf bir hesapla yazıldığı durumlar da ayrıca ölçülmedi.

### Zincirde İki map

Boş kutu bir `map` çağrısından boş çıkıyorsa, ardına eklenen ikinci `map` de aynı kutuyla karşılaşır. Zincirin ilk halkası hiçbir şey üretmediğinde sonraki halkalar üretecek bir değer bulamaz. Bunu iki dönüştürücüyle ölçelim; her dönüştürücünün gövdesi kendi `Probe`'una bağlıdır ve zincir her kullanımda baştan kurulur.

```swift
// main.swift — bos kutuda zincirdeki her map atlanir
let stageOne = Probe("zincir-birinci")
let stageTwo = Probe("zincir-ikinci")
let seed: Int? = Int("on")

for _ in 1...2 {
    _ = stageOne.use { seed.map { stageOne.eval($0 + 1) }.map { stageTwo.eval($0 * 2) } }
    _ = stageTwo.use { seed.map { stageOne.eval($0 + 1) }.map { stageTwo.eval($0 * 2) } }
}
stageOne.report()
stageTwo.report()
```

```
zincir-birinci: 0 degerlendirme, 2 kullanim -> hic
zincir-ikinci: 0 degerlendirme, 2 kullanim -> hic
```

İki dönüştürücü de hiç değerlendirilmedi. İkincinin hiç çalışmaması beklenebilirdi, çünkü kendi girdisi birincinin sonucudur; birincinin hiç çalışmaması ise kutunun en başta boş olmasından gelir. `seed` değeri `Int("on")` ile kurulduğu için `nil`'dir; ilk `map` boş kutuyu dönüştürmeden geçirir, ikinci `map` de aynı boş kutuyu alır. Uzun bir dönüştürücü zincirinde en baştaki bir yokluk bu yüzden sonraki halkaların hiçbirini koşturmaz.

**TS2.** Bu zincirde yalnız başlangıç değeri boştur; zincirin ortasındaki bir dönüştürücünün `nil` döndürdüğü durum bu ölçümde yok ve orada sonraki `map`in davranışı ayrıca ölçülmedi.

## map ile flatMap

Dönüştürücünün kendisi de isteğe bağlı bir değer döndürebilir. Bir metni tamsayıya çeviren `Int($0)` tam böyle bir ifadedir: sonucu `Int?`'tir. `map` dönüştürücünün sonucunu olduğu gibi ayrı bir kutuya koyar, bu yüzden kutunun içine bir kutu girer. `flatMap` ise dönüştürücünün döndürdüğü kutuyu dışarıya düzleştirir. Üç girdiyle farkı görelim: bir geçerli metin, bir geçersiz metin ve bir boş kutu.

```swift
// main.swift — map ic ice katman uretir, flatMap duzlestirir
let inputs: [String?] = ["7", "x", nil]
for input in inputs {
    let nested = input.map { Int($0) }
    let flat = input.flatMap { Int($0) }
    print(nested, flat)
}
```

```
Optional(Optional(7)) Optional(7)
Optional(nil) nil
nil nil
```

Birinci satırda `map` iki katmanlı bir sonuç verir, `flatMap` tek katmanlı. İkinci satır asıl farkı gösterir: `"x"` geçersiz bir metindir ve `map` sonucu `Optional(nil)` olur, yani dış kutu dolu, iç kutu boştur; `flatMap` ise doğrudan `nil` verir. Üçüncü satırda girdinin kendisi boş olduğu için iki yöntem de dönüştürücüye hiç uğramaz ve `nil` döner.

İkinci satır sonraki ölçümün zeminidir. `Optional(nil)` ile `nil` birbirinden ayrı değerlerdir ve ikisi de yokluk anlatır; fakat biri yokluğu bir katman içeride, öbürü en dışta taşır. Hangi katmanda durduğu, bir sonraki yöntemin dönüştürücüyü çağırıp çağırmayacağını belirler.

**TS3.** Bu çıktı yalnız `Int` dönüştürmesi için; dönüştürücünün başka bir tipe çevirdiği ya da hata fırlattığı durumlar denenmedi. Çıktıdaki `Optional(...)` yazımı bu sürümün `print` biçimidir; ölçülen şey katman sayısıdır, biçimin kendisi değil.

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

Ders başında `map` için bir kural kurduk: boş kutuda dönüştürücü çalışmaz. Kural doğru, ama hangi kutunun boş sayıldığı bir katman sorusudur. `Int??` tipi iki katmanlı bir kutudur. Dış kutu doluyken içindeki kutu boş olabilir; bu durum `.some(nil)` diye yazılır. Aşağıda iki değer var: dış katmanı dolu olan ama içi boş bir değer ve en dışta boş olan bir değer. Her ikisine de `map` uygulanır ve dönüştürücü, aldığı değerin `nil` olup olmadığını döndürür.

```swift
// main.swift — dis katman doluysa yokluk iceride olsa da map kosar
let outer = Probe("dis-katman-dolu")
let hollow = Probe("dis-katman-bos")
let inner: Int?? = .some(nil)
let empty: Int?? = nil

for _ in 1...2 {
    _ = outer.use { inner.map { value in outer.eval(value == nil) } }
    _ = hollow.use { empty.map { value in hollow.eval(value == nil) } }
}
outer.report()
hollow.report()
print(inner.map { $0 == nil })
print(empty.map { $0 == nil })
```

```
dis-katman-dolu: 2 degerlendirme, 2 kullanim -> her-kullanimda
dis-katman-bos: 0 degerlendirme, 2 kullanim -> hic
Optional(true)
nil
```

Dış katmanı dolu olan değerde dönüştürücü çalıştı ve `nil` aldı: sonuç `Optional(true)`'dur, çünkü dönüştürücü içerideki yokluğu `true` olarak döndürdü. En dışta boş olan değerde dönüştürücü hiç çalışmadı. Yani `map` için yokluk, yalnızca en dış kutunun boş olmasıdır; içeride yokluk taşıyan ama dışı dolu bir değer, `map` açısından doludur.

Bu sonuç, dersin kuralının geçerli olduğu alanı daraltır. Dönüştürücü kapanışın hiç değerlendirilmemesi, kutunun **dış katmanının** boş olmasına bağlıdır. İç içe isteğe bağlı değerlerle çalışırken `map` yokluğu "bir katman yukarı" taşımaz: iç katmandaki yokluğu dönüştürücüye değer olarak verir. Bu yüzden önceki bölümdeki `Optional(nil)` sonucu, sonraki bir `map` çağrısı için dolu bir kutudur. Katman sayısını azaltmak istendiğinde `flatMap` kullanılır.

**TS4.** Bu ölçüm iki katmanlı bir kutu için; üç ya da daha çok katmanlı kutular denenmedi. Dönüştürücünün `nil` aldığını biz `value == nil` karşılaştırmasıyla gözlemledik; başka bir gözlem biçimi denenmedi.

## Özet

- `Int?` ile `Int` ayrı tiplerdir; yokluk tipin içinde taşınır ve derleyici kontrolü zorunlu kılar.
- Optional bir numaralandırmadır: `.some` bir değer taşır, `.none` (yani `nil`) hiçbir değer taşımaz.
- Boş kutuda `map` dönüştürücü kapanışı hiç çağırmaz; dolu kutuda her çağrıda yeniden koşturur.
- Dönüştürücü isteğe bağlı bir değer döndürdüğünde `map` katman ekler, `flatMap` düzleştirir; `Optional(nil)` ile `nil` ayrı değerlerdir.
- Dış katmanı dolu olan `Int??` içinde yokluk bulunsa bile `map` dönüştürücüyü çalıştırır.
- Bu dersin anı: **hiç**. Boş bir kutuda `map` dönüştürücüsü hiç değerlendirilmez.

## Sonraki Adım

Bu derste kutuyu açmadan çalıştık: `map` ve `flatMap` değeri dönüştürdü ama sonucu yine bir kutuda bıraktı. Gerçek bir değere ihtiyaç duyulduğunda kutunun açılması gerekir. Bir sonraki ders açmanın yollarını ölçer: `if let` ile `guard let` sağ tarafı ne zaman değerlendirir, `??` zinciri kaçıncı adayda durur ve isteğe bağlı zincirleme `nil` gördüğünde zincirin geri kalanına ne yapar.
