İçeriğe geç
Educora
Orta18 dk6 / 14

Fonksiyonlar ve closure'lar

Kodu fonksiyonlara böl: argüman etiketleri, varsayılan değerler ve dönüş değerleri. Ardından closure'ları, kısa yazımlarını ve sondaki closure'ları öğren.

Kendini test et
Bu derste öğreneceklerin
  • Parametreli ve değer döndüren fonksiyonlar yazmak ve çağırmak
  • Argüman etiketlerini, _ işaretini ve varsayılan parametre değerlerini kullanmak
  • Closure yazmak, kısaltmak ve sondaki closure sözdizimini tanımak

Uygulamanda bilet fiyatını on farklı yerde hesapladığını düşün. Kurallar değiştiğinde on yeri düzeltmen gerekir ve birini mutlaka unutursun. Çözüm bir fonksiyondur: kodu bir kez yazar, ona bir ad verir ve gereken her yerde çağırırsın. print, sorted(), map gibi hazır fonksiyonları zaten kullandın; şimdi kendi fonksiyonlarını yazacaksın.

Fonksiyon tanımlamak

Fonksiyon func anahtar sözcüğüyle başlar. Parantez içine parametreler türleriyle birlikte yazılır, -> işaretinden sonra da döndürülen değerin türü gelir. return sonucu geri gönderir. Fonksiyonun gövdesi tek bir ifadeden oluşuyorsa return sözcüğünü yazmayabilirsin.

Swift
func greet(name: String) -> String {
    return "Hello, \(name)!"
}

func square(_ x: Int) -> Int {
    x * x
}

print(greet(name: "Aysel"))
print(square(7))
print(square(square(2)))
Beklenen çıktı
Hello, Aysel!
49
16

Argüman etiketleri ve varsayılan değerler

Swift'te çağrı bir cümle gibi okunsun diye her parametrenin iki adı olabilir: argüman etiketi (çağırırken yazılır) ve parametre adı (fonksiyonun içinde kullanılır). travel(from start: String, to end: String) fonksiyonu travel(from: "Baku", to: "Shaki") diye çağrılır. Etiket istemiyorsan yerine _ yazılır; square(7) tam olarak böyle çalışır.

Bir parametreye varsayılan değer verilebilir: çağırırken onu atlarsan bu değer kullanılır. Aşağıda bilet 12 yaşından küçükler için 5, öğrenciler için 7,5, diğer herkes için 10 manattır.

Swift
func travel(from start: String, to end: String) {
    print("Travelling from \(start) to \(end)")
}

func ticketPrice(for age: Int, isStudent: Bool = false) -> Double {
    if age < 12 {
        return 5.0
    } else if isStudent {
        return 7.5
    }
    return 10.0
}

travel(from: "Baku", to: "Shaki")
print(ticketPrice(for: 8))
print(ticketPrice(for: 20))
print(ticketPrice(for: 20, isStudent: true))
Beklenen çıktı
Travelling from Baku to Shaki
5.0
10.0
7.5

Closure'lar

Tanım
Closure (kapanış)

Adı olmayan, bir değişkene kaydedilebilen ve başka bir fonksiyona aktarılabilen kod bloğu. Süslü parantez içinde yazılır: önce parametreler ve dönüş türü, sonra in sözcüğü, ardından gövde gelir.

Swift, closure'ları adım adım kısaltmana izin verir: türleri bağlamdan çıkarır, tek ifadede return istemez ve parametrelere $0, $1 adlarıyla erişmeye izin verir. Aşağıda aynı sıralama dört kez, giderek kısalarak yazılmıştır:

Swift
let double = { (x: Int) -> Int in
    return x * 2
}
print(double(5))

let numbers = [5, 2, 9, 1]
print(numbers.sorted(by: { (a: Int, b: Int) -> Bool in
    return a > b
}))
print(numbers.sorted(by: { a, b in a > b }))
print(numbers.sorted { $0 > $1 })
print(numbers.sorted(by: >))
Beklenen çıktı
10
[9, 5, 2, 1]
[9, 5, 2, 1]
[9, 5, 2, 1]
[9, 5, 2, 1]

Sondaki closure'lar

Bir closure fonksiyonun son argümanıysa parantezden sonra yazılabilir; buna sondaki closure (trailing closure) denir. numbers.sorted { $0 > $1 } ve prices.map { $0 * 2 } tam olarak böyle yazılmıştır. Closure alan kendi fonksiyonunu da yazabilirsin; parametresinin türü () -> Void gibi bir fonksiyon türüdür.

Swift
func repeatTask(times: Int, task: () -> Void) {
    for _ in 1...times {
        task()
    }
}

repeatTask(times: 3) {
    print("Hip hip hooray!")
}

func apply(_ value: Int, _ operation: (Int) -> Int) -> Int {
    operation(value)
}

func triple(_ x: Int) -> Int {
    x * 3
}

print(apply(4) { $0 + 10 })
print(apply(4, triple))
Beklenen çıktı
Hip hip hooray!
Hip hip hooray!
Hip hip hooray!
14
12
Bir fonksiyona hem closure hem de adı olan başka bir fonksiyon aktarılabilir.

Closure'lar oluşturuldukları yerdeki değişkenleri hatırlar (İngilizcesiyle capture, yakalama). Aşağıdaki makeCounter, her çağrıda bir artan bir sayaç döndürür: count değişkeni fonksiyon bittikten sonra da closure'ın içinde yaşamaya devam eder.

Swift
func makeCounter() -> () -> Int {
    var count = 0
    return {
        count += 1
        return count
    }
}

let counter = makeCounter()
print(counter())
print(counter())
print(counter())
Beklenen çıktı
1
2
3

Önemli noktalar

  • Fonksiyon func ad(parametre: Tür) -> DönüşTürü { ... } biçiminde tanımlanır.
  • Argüman etiketi çağrıda, parametre adı fonksiyonun içinde kullanılır; _ etiketi kaldırır.
  • Varsayılan değeri olan bir parametre çağrıda atlanabilir.
  • Closure adsız bir fonksiyondur; $0 ve $1 onun parametreleridir.
  • Son argüman olan closure parantezden sonra yazılabilir; closure'lar çevresindeki değişkenleri hatırlar.

Kendini test et

10 soru. Her doğru cevap XP kazandırır.

1 / 10
func travel(from start: String, to end: String) fonksiyonunun doğru çağrısı hangisidir?