---
title: Fonksiyonlar
source: 'https://academia.sh/tr/kurslar/swift/fonksiyonlar'
course: 'Swift Dili'
language: tr
updated: '2026-10-21T05:03:11+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Argüman etiketi, varsayılan değer, demetle dönüş ve `inout` kullanmak'
    - 'Varsayılan argüman ifadesinin her çağrıda değerlendirildiğini göstermek'
    - 'Argüman verilince varsayılan ifadenin hiç değerlendirilmediğini açıklamak'
    - 'Argümanın gövde okumasa da çağrıdan önce değerlendirildiğini söylemek'
---

# Fonksiyonlar

Argüman etiketlerini, varsayılan değerleri, demetle çoklu dönüşü ve `inout` parametreyi tanıtır; varsayılan argüman ifadesinin her çağrıda değerlendirildiğini ölçer.

Denetim akışında koşullar yalnız gerektiğinde değerlendirildi. Fonksiyonlarda soru bir adım ileri gidiyor: bir çağrının argümanı ne zaman değerlendirilir, bir parametrenin varsayılan değeri ne zaman? Swift'te bir fonksiyon, çağıranın okuyabileceği bir cümle gibi görünmek için tasarlanmıştır; bu dersin ölçümü o cümlenin arkasındaki değerlendirme sırasını gösterir.

## Etiketler, Varsayılanlar ve Dönüş

Swift'te her parametrenin bir argüman etiketi (argument label) vardır ve çağrıda yazılır. `func move(from start: Int, to end: Int)` tanımında `from` ve `to` çağıranın gördüğü etiketlerdir, `start` ve `end` ise gövdenin kullandığı adlardır. Etiket yerine alt çizgi yazarsan çağrıda etiket olmaz: `func pad(_ text: String)`. Bir parametreye `= değer` eklemek varsayılan argüman (default argument) tanımlar; çağıran o parametreyi vermezse varsayılan ifade kullanılır.

Bir fonksiyon birden çok değer döndürmek için bir demet (tuple) döndürebilir: `-> (low: Int, high: Int)`. Etiketli demet çağıran tarafta `result.low` biçiminde okunur. `inout` parametre ise fonksiyonun çağıranın değişkenini değiştirmesini sağlar; çağrıda değişkenin önüne `&` yazılır ve değişken `var` olmak zorundadır.

```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)")
    }
}
```

Ölçüm bloğu önce bu dört özelliği çalıştırır. Ardından aynı gövdeye sahip iki fonksiyon kurar: `pad` genişliği çağıran vermezse bir `Probe` üzerinden varsayılan değeri alır, `padGiven` ise aynı varsayılana sahiptir ama biz her çağrıda genişliği kendimiz veririz. Fonksiyonlar `@MainActor` işaretlidir, çünkü varsayılan ifade üst düzeydeki `Probe`'u okur ve `Probe` Swift 6 kurallarında yalnız ana aktörden okunabilir.

```swift
// main.swift — etiket, varsayilan, demet ve inout
func move(from start: Int, to end: Int) -> Int { end - start }
func bounds(of values: [Int]) -> (low: Int, high: Int) {
    (values.min() ?? 0, values.max() ?? 0)
}
func increment(_ value: inout Int) { value += 1 }

print(move(from: 2, to: 5))
let found = bounds(of: [3, 1, 2])
print(found.low, found.high)
var total = 0
increment(&total)
increment(&total)
print(total)

let defaultProbe = Probe("varsayilan-ifade")
let givenProbe = Probe("verilen-iken-varsayilan")

@MainActor func pad(_ text: String, width: Int = defaultProbe.eval(6)) -> String {
    String(repeating: "*", count: width) + text
}

@MainActor func padGiven(_ text: String, width: Int = givenProbe.eval(6)) -> String {
    String(repeating: "*", count: width) + text
}

print(defaultProbe.use { pad("a") })
print(defaultProbe.use { pad("b") })
print(givenProbe.use { padGiven("c", width: 2) })
print(givenProbe.use { padGiven("d", width: 2) })

let allProbes = [defaultProbe, givenProbe]
for probe in allProbes { probe.report() }
tally(allProbes)
```

```
3
1 3
2
******a
******b
**c
**d
varsayilan-ifade: 2 degerlendirme, 2 kullanim -> her-kullanimda
verilen-iken-varsayilan: 0 degerlendirme, 2 kullanim -> hic
hemen: 0
ilk-kullanimda: 0
her-kullanimda: 1
hic: 1
```

`move` çağrısı 3 verdi, `bounds` demeti `1 3` olarak okundu ve iki `increment` çağrısı `total` değişkenini 2 yaptı. Ölçümün asıl satırları sondadır. `varsayilan-ifade`, iki çağrıda iki kez değerlendirildi: varsayılan ifade fonksiyon tanımında bir kez hesaplanıp saklanmaz, her çağrıda yeniden çalışır ve sonucu `her-kullanimda` olur. `verilen-iken-varsayilan` ise iki çağrıda sıfır değerlendirme gösterdi, çünkü çağıran genişliği kendisi verdi ve varsayılan ifadeye hiç uğranmadı: `hic`.

**DT46.** Varsayılan argüman ifadesi `@MainActor` bir fonksiyonda ve yalnız sabit bir tam sayı için ölçüldü; başka tiplerde ya da `nonisolated` bağlamda aynı sonucun çıkması bu dersin iddiası değildir.

**DT47.** Varsayılan ifadenin çağıranın bağlamında mı çağrılanın bağlamında mı çalıştığı bu derste ayırt edilmiyor; ölçülen şey kaç kez ve ne zaman değerlendirildiğidir.

## Değişken Sayıda Parametre

Bir parametrenin tipinden sonra üç nokta yazarsan fonksiyon o noktada istediğin kadar argüman alır: `func sumAll(of numbers: Int...) -> Int`. Fonksiyon gövdesinde `numbers` sıradan bir `[Int]` dizisidir. Çağrıda argümanları virgülle yazarsın; hiç argüman vermeye de izin verilir ve bu durumda dizi boş gelir. Bir fonksiyonda birden çok değişken sayıda parametre olabilir; ilkinden sonra gelen parametrenin argüman etiketi taşıması gerekir.

Argümanlar çağrıdan önce değerlendirilir; üç argüman üç ifade demektir. Aşağıdaki blok her argümanını bir `Probe`'dan geçiren iki çağrı yapar ve bir de argümansız çağrı ekler.

```swift
// Variadic.swift — degisken sayida parametre
func sumAll(of numbers: Int...) -> Int {
    numbers.reduce(0, +)
}
let variadicProbe = Probe("degisken-sayi")
print(variadicProbe.use {
    sumAll(of: variadicProbe.eval(1), variadicProbe.eval(2), variadicProbe.eval(3))
})
print(variadicProbe.use {
    sumAll(of: variadicProbe.eval(4), variadicProbe.eval(5))
})
print(sumAll())
variadicProbe.report()
```

```
6
9
0
degisken-sayi: 5 degerlendirme, 2 kullanim -> her-kullanimda
```

Üç sayının toplamı 6, iki sayının toplamı 9, argümansız çağrı 0 verdi. `Probe` beş değerlendirme gösterdi: ilk çağrıda üç, ikincisinde iki. Her argüman kendi ifadesidir ve çağrıdan önce hesaplanır; fonksiyon gövdesi dizi olarak hazır alır. Bu yüzden an `her-kullanimda` okunur.

Değişken sayıda parametre çağıran tarafı sadeleştirir, çünkü bir dizi kurmak gerekmez. Argümanların sayısı çağrıya göre değişir; ölçüm bu değişimin değerlendirme sayısını da değiştirdiğini gösteriyor.

**DT48.** Değişken sayıda parametre `Int` ile ölçüldü; Swift'te bir diziyi değişken parametreye yaymanın yolu yoktur; dizi almak gerekiyorsa parametre `[Int]` olarak tanımlanır.

## İç İçe Fonksiyon Çevresini Yakalar

Bir fonksiyonun içinde başka bir fonksiyon tanımlayabilirsin. İç fonksiyon, dış fonksiyonun yerel değişkenlerini ve parametrelerini görür ve onları yakalar. Dış fonksiyon iç fonksiyonu döndürürse, yakalanan değişkenler dış fonksiyon bittikten sonra da yaşamaya devam eder. Bu, her çağrıda kendi durumunu taşıyan bir sayaç yapmanın yoludur.

Aşağıdaki blok `makeCounter` adlı bir fonksiyon yazar. Fonksiyon bir başlangıç değeri alır, içindeki `advance` adlı iç fonksiyon her çağrıda sayıyı bir artırıp bir `Probe`'dan geçirir ve iç fonksiyonu döndürür. İki bağımsız sayaç kurulur: ilki iki kez, ikincisi bir kez çağrılır.

```swift
// Counter.swift — ic fonksiyon durum tasir
func makeCounter(start: Int, probe: Probe) -> () -> Int {
    var current = start
    func advance() -> Int {
        current += 1
        return probe.eval(current)
    }
    return advance
}
let nestedProbe = Probe("ic-fonksiyon")
let first = makeCounter(start: 10, probe: nestedProbe)
let second = makeCounter(start: 100, probe: nestedProbe)
print(nestedProbe.use { first() })
print(nestedProbe.use { first() })
print(nestedProbe.use { second() })
nestedProbe.report()
```

```
11
12
101
ic-fonksiyon: 3 degerlendirme, 3 kullanim -> her-kullanimda
```

İlk sayaç 11 ve 12, ikinci sayaç 101 verdi. İki sayaç aynı fonksiyondan çıktığı hâlde ayrı bir `current` yakaladı; biri ilerlerken öbürü etkilenmedi. Üç çağrı üç değerlendirme getirdi ve an `her-kullanimda` olur. `makeCounter` bittikten sonra bile `current` yaşıyor, çünkü iç fonksiyon onu tutuyor.

Bu, bir sonraki dersin konusunu hazırlar: iç fonksiyon, kapanışın adı konmuş hâlidir. Yakalama kuralları aynıdır.

**DT49.** İç fonksiyon bir `Int` durumu yakaladı; yakalanan değerin sınıf örneği olduğu durumlar bu dersin dışındadır.

## inout Geri Yazar

`inout` parametre, çağıranın değişkenini fonksiyonun değiştirmesine izin verir. Mekanizma "kopyala, değiştir, geri yaz" biçimindedir: fonksiyon değişkenin bir kopyasını alır, gövdede onu istediği kadar değiştirir ve fonksiyon bitince sonucu değişkene tek seferde geri yazar. Değişkenin gözlemcisi varsa (`didSet`), gözlemci gövdedeki değişikliklerin her birinde değil, geri yazma anında bir kez çalışır. Doğrudan atama ise her satırda gözlemciyi çalıştırır.

Aşağıdaki blok aynı işi iki yolla yapar: biri `inout` parametreli bir fonksiyonla iki kez artırır, öbürü iki artırmayı doğrudan yazar. İki değişkenin de bir `didSet` gözlemcisi var ve her gözlemci kendi `Probe`'una yazar. İki yol da iki tur çalıştırılır.

```swift
// Inout.swift — inout geri yazma
func addTwice(_ value: inout Int) {
    value += 1
    value += 1
}
let viaCallProbe = Probe("inout-gozlemci")
let directProbe = Probe("dogrudan-gozlemci")
var viaCall = 0 { didSet { _ = viaCallProbe.eval(viaCall) } }
var direct = 0 { didSet { _ = directProbe.eval(direct) } }
_ = viaCallProbe.use { addTwice(&viaCall) }
_ = viaCallProbe.use { addTwice(&viaCall) }
_ = directProbe.use { direct += 1; direct += 1 }
_ = directProbe.use { direct += 1; direct += 1 }
print(viaCall, direct)
viaCallProbe.report()
directProbe.report()
```

```
4 4
inout-gozlemci: 2 degerlendirme, 2 kullanim -> her-kullanimda
dogrudan-gozlemci: 4 degerlendirme, 2 kullanim -> her-kullanimda
```

İki değişken de 4 oldu, ama gözlemci sayıları ayrıştı: `inout` yolu iki değerlendirme, doğrudan yol dört değerlendirme gösterdi. `addTwice` gövdede iki kez artırdı; gözlemci geri yazma anında, çağrı başına bir kez çalıştı. Doğrudan yolda her `+=` kendi gözlemcisini tetikledi. İki satır da `her-kullanimda` okunur, ama sayıları fark eder.

Bu fark `inout` ile gözlemci bir arada olduğunda dikkat gerektirir: gözlemcinin görmediği ara değerler olabilir. Ara durumları görmek istiyorsan doğrudan yaz, yalnız sonucu istiyorsan `inout` yeterlidir.

**DT50.** Gözlemci sayısı üst düzey bir değişkenle ölçüldü; sınıf özelliklerinde ve yapı özelliklerinde `inout` geri yazmasının aynı sayıyı verdiği bu dersin dışındadır.

## Fonksiyon Tipi ve Değer Olarak Fonksiyon

Her fonksiyonun bir tipi vardır: parametre tiplerinin ve dönüş tipinin birleşimi. `func triple(_ n: Int) -> Int` fonksiyonunun tipi `(Int) -> Int` yazılır. Bu tip, sıradan bir tip gibi kullanılır: bir sabite atayabilir, bir parametre tipi olarak yazabilir ya da başka bir fonksiyondan döndürebilirsin. Fonksiyonu bir sabite atamak onu çağırmaz; yalnız onu bir değer olarak taşır. Çağrı, ancak parantezle yapılır.

Aşağıdaki blok `triple` fonksiyonunu bir sabite atar, tipini yazdırır ve onu `apply` adlı başka bir fonksiyona argüman olarak geçirir. `apply` verilen fonksiyonu bir değere uygular. Uygulanacak değer bir `Probe`'dan gelir ve `apply` iki kez çağrılır.

```swift
// FunctionType.swift — fonksiyon tipi
func triple(_ n: Int) -> Int { n * 3 }
func apply(_ transform: (Int) -> Int, to value: Int) -> Int {
    transform(value)
}
let typeProbe = Probe("fonksiyon-tipi")
let transform = triple
print(type(of: transform))
print(typeProbe.use { apply(transform, to: typeProbe.eval(4)) })
print(typeProbe.use { apply(transform, to: typeProbe.eval(5)) })
typeProbe.report()
```

```
@Sendable (Int) -> Int
12
15
fonksiyon-tipi: 2 degerlendirme, 2 kullanim -> her-kullanimda
```

`type(of: transform)` `@Sendable (Int) -> Int` yazdırdı: tip, parametre ve dönüş tipine ek olarak bir `@Sendable` niteliği taşıyor, çünkü üst düzey fonksiyonlar eşzamanlı ortamlarda güvenle paylaşılabilir. Okunuşta `(Int) -> Int` kısmı belirleyicidir. `apply` iki çağrıda `12` ve `15` verdi: `4 * 3` ve `5 * 3`. `Probe` iki değerlendirme gösterdi; her çağrıda argüman, `apply` çalışmadan önce bir kez hesaplandı. `transform` sabitinin kendisi bir değerlendirme sayılmadı, çünkü fonksiyonu bir sabite atamak onu çalıştırmaz.

Fonksiyonu değer olarak taşıdığında çağırma anı sende kalır: onu ne zaman, kaç kez ve hangi argümanla çağıracağın, çağrı yerinde belli olur.

Fonksiyon tipini bir kez okumayı öğrendiğinde, standart kütüphanedeki imzalar da okunur hâle gelir. Bir dizinin `map` yöntemi bir `(Element) -> T` fonksiyonu bekler; ona adlı bir fonksiyon da verebilirsin, bir kapanış da. Sonraki derste göreceğin kapanış, adı olmayan bir fonksiyon değeridir ve aynı tip kurallarına uyar.

Tipin başındaki `@Sendable` niteliği şimdilik dikkate alınmayabilir; onu sonraki konularda eşzamanlılıkla birlikte göreceksin. Önemli olan, fonksiyonun bir değer olarak taşındığını ve çağrı parantezi gelmedikçe çalışmadığını bilmektir. Aynı fonksiyonu iki farklı değişkene atamak iki ayrı kopya üretmez; ikisi de aynı fonksiyona işaret eder.

Çağrıdan önce hesaplanan şey argümandır, fonksiyon değeri değil; ölçümün iki değerlendirmesi bunu doğruluyor.

**DT51.** Fonksiyon tipi tek parametreli bir fonksiyonla ölçüldü; birden çok parametreli ve fonksiyon döndüren fonksiyonlar bu dersin dışındadır.

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

Varsayılan değer çağıran vermediğinde devreye girer. Çağıran bir argüman verdiğinde ise iş tersine döner: o ifade çağrıdan önce değerlendirilir, fonksiyon gövdesi onu okusun ya da okumasın. Bu, dil açısından sıradan bir kuraldır, ama ölçüm bunu göstermeden önce bir sezgi bırakır: okunmayan bir parametrenin argümanı hiç değerlendirilmez gibi görünür. Aşağıdaki gövde parametresini hiç okumaz, ve `marked` yardımcı fonksiyonu argümanın ne zaman çalıştığını `print` ile gösterir.

```swift
// main.swift — argüman gövdeden once degerlendirilir
func marked(_ n: Int) -> Int {
    print("arguman \(n)")
    return n
}

func ignore(_ value: Int) -> String {
    print("govde calisti")
    return "okumadi"
}

let argumentProbe = Probe("arguman-ifadesi")
_ = argumentProbe.use { ignore(argumentProbe.eval(marked(7))) }
_ = argumentProbe.use { ignore(argumentProbe.eval(marked(8))) }

let allProbes = [argumentProbe]
for probe in allProbes { probe.report() }
tally(allProbes)
```

```
arguman 7
govde calisti
arguman 8
govde calisti
arguman-ifadesi: 2 degerlendirme, 2 kullanim -> her-kullanimda
hemen: 0
ilk-kullanimda: 0
her-kullanimda: 1
hic: 0
```

`arguman 7` satırı `govde calisti` satırından önce basıldı, hem de gövde `value` parametresini hiç kullanmadığı hâlde. `arguman-ifadesi` iki çağrıda iki kez değerlendirildi: argüman, fonksiyon çağrılmadan önce her seferinde hesaplanır. Varsayılan ifade ile arasındaki fark şudur: varsayılan ifade yalnız argüman verilmediğinde çalışır, verilen argüman ise her zaman çalışır.

**DT52.** `ignore` gövdesinin parametreyi okumaması, derleyicinin argüman ifadesini eleyip elemediğini ölçmez; çıktıda `arguman 7` satırı bu ölçümün tek kanıtıdır ve yalnız bu yapı için geçerlidir.

## Özet

- Argüman etiketi çağrıyı okunur kılar; `_` etiketi kaldırır, `= değer` varsayılan argüman tanımlar.
- Demet birden çok değer döndürür; `inout` parametre çağıranın `var` değişkenini `&` ile değiştirir.
- Varsayılan argüman ifadesi her çağrıda, argüman verilmediğinde değerlendirilir.
- Argüman verilirse varsayılan ifade hiç değerlendirilmez; verilen argüman gövde okumasa da çağrıdan önce değerlendirilir.
- Bu dersin anı: **her kullanımda** (varsayılan argüman ifadesi).

## Sonraki Adım

Bir fonksiyon, parametresi olarak başka bir fonksiyon alabilir ve bunu isimsiz bir ifade olarak yazabilirsin. Bu ifadenin gövdesi ne zaman çalışır ve çevresindeki değişkenleri hangi anda görür? Sıradaki ders kapanışlara bakıyor.
