Nedir Bu Closure?

İkranur Bulut
FLO Teknoloji
3 min readApr 11, 2023

--

Herkese merhaba, bugün değinmek istediğim konu Swift yazmaya başlanıldığında karışık gelen ve aslında farketmeden kullandığımız Closure .

Az laf çok code diyerek elimden geldiğince örneklerle açıklamaya çalışacağım.

Closures are self-contained blocks of functionality that can be passed around and used in your code.
Swift Doc.

Closures are self-contained bunch of words passed around like a damn basketball.
Swift Doc.

Swift’in kendi dökümanında yapılan açıklamalar biraz kafa karıştırıcı bu yüzden örnek kodlarla ve fonksiyonla karşılaştırma yaparak ilerlediğimizde daha açıklayıcı olacağını düşünüyorum.

Closure’lar aslında bir fonksiyon. Ama “func” ve “func name” olmayan hali.

Peki neden Closure ?

Bu closure’ların bir anlamı olmalı…

Çünkü sahip oldukları syntax daha kolay

Fonksiyon ve Closure karşılaştırması yaparak devam edelim.

Fonksiyonlar

– Fonksiyonların adı vardır
“func” keyword’üne sahiptirler

func sayHelloToUser(userName: String) -> String {
return "Hello \(userName)"
}

//call func
sayHelloToUser(userName: "Ikra")
//return: Hello Ikra

Closure’lar

– Herhangi bir adı yoktur
– Bir keyword’e sahip değillerdir

var sayHelloToUser = { (userName: String) -> String in
//(String) -> String
return "Hello \(userName)"
}

//call closure
sayHelloToUser("Ikra")
//return: Hello Ikra

Örneklerde de farkedileceği gibi clouser’lar { ile başlar } ile biter. Dönülen return type belirtildikten sonra in keyword’ü kullanılır.

Yazdığımız closure’ ı daha da kısa hale çevirebiliriz.

var sayHelloToUser = { (userName: String) in
//(String) -> String
return "Hello \(userName)"
}

sayHelloToUser("Ikra")
//return: Hello Ikra

Swift tahmin ettiğimizden daha zeki aslında. Burada herhangi bir return type belirtmeden direkt return etmesini istediğimiz şekilde bir kod yazdığımızda swift bunu Type Inference özelliği sayesinde return type’ın String olduğunu anlar.

Basit bir örnekle devam edelim;

Burada tıpkı fonksiyonlarda olduğu gibi closure’ların da birden fazla parametre aldığını görebiliriz.

func returnFullname(firstName: String, lastName: String) -> String {
return "\(firstName) \(lastName)"
}

returnFullname(firstName: "Ikranur", lastName: "Bulut")
//return: İkranur Bulut

var returnFullname = { (firstName: String, lastName: String) in
//(String, String) -> String
"\(firstName) \(lastName)"
}

returnFullname("Ikranur", "Bulut")
//return: İkranur Bulut

Bu syntax’ların bir yerlerden tanıdık geliyor olması lazım.

Çoğu zaman kullandığımız filter, map, sorted gibi metodların aslında her biri bir closure’dır.

Bu metodları kullanarak örnek üzerinden ilerleyelim. Elimizde User adında bir struct tanımlı olsun. User’ın name ve age şeklinde iki tane property’si olduğunu düşünelim ve bu struct’an oluşan users array’i oluşturalım.

struct User {
var name: String
var age: Int
}

let users = [User(name: "John", age: 20),
User(name: "Kate", age: 22),
User(name: "Anna", age: 22),
User(name: "Daniel", age: 39),
User(name: "David", age: 34),
User(name: "John", age: 55),
User(name: "Hank", age: 18),
User(name: "Justin", age: 24),
User(name: "Bill", age: 26)]

Bu arraydan eğer 30 yaş üstü insanları filtrelemek için bir closure yazmak istersek şu şekilde olur;

Closure syntax

{ (<#parameters#>) -> <#return type#> in
<#statements#>
}
var middleAgeUserFilter: (User) -> Bool = { user in
return user.age > 30
}

Syntax’ta da görüldüğü üzere parameter burada tek bir tane ve o da User, return type Bool, statement ise user.age > 30.

Bunu fonksiyon şeklinde yazmak isteseydik eğer o da şu şekilde olacaktı;

func middleAgeUserFilterFunc(user: User) -> Bool {
return user.age > 30
}

Yukarıda yazdığımız closure’ı daha da kısa bir şekilde az önce bahsettiğim metodlardan biri olan filter ile yazabiliriz.

let middleAgeUsers = users.filter { user in
return user.age > 30
}

//return: {name: "Daniel", age: 39}
// {name: "David", age: 34}
// {name: "John", age: 55}

Yukarıda bulunan kod parçacığı ile aşağıda bulunan kod parçacığının tek farkı yazım şekilleri.

let middleAgeUsers = users.filter { $0.age > 30 }

Buradaki $0 aslında array’in her bir elemanını temsil ediyor. Yani her bir user’a erişebilmemizi sağlıyor. Bu sayede user’ın age’ine erişip 30’ dan büyükleri filtrelere diyebiliyoruz.

Aynı şey sorted metodu içinde geçerli. Array’i user’ın ismine göre alfabetik sıralamak istersek eğer şu şekilde bir yol izlememiz gerekiyor

let sortedUsers = users.sorted { $0.name < $1.name }

//{name: "Anna", age: 22}
//{name: "Bill", age: 26}
//{name: "Daniel", age: 39}
//{name: "David", age: 34}
//{name: "Hank", age: 18}
//{name: "John", age: 20}
//{name: "John", age: 55}
//{name: "Justin", age: 24}
//{name: "Kate", age: 22}

filterda olduğu gibi buradaki $0 ve $1 array’in o anki index’ini ve bir sonraki index’ini temsil ediyor. User’ın isimlerini ise < kullanarak alfabetik bir şekilde sıraya dizebiliyoruz.

Umarım makalemden okurken keyif almış ve bir şeyler öğrenmişsinizdir. Bol kodlu günler .

--

--