# Fonksiyonlar (Functions)

Dart, gerçek bir nesne yönelimli dil olduğu için fonksiyonlar bile nesnelerdir ve bir tipe sahiptirler. Bu, fonksiyonların değişkenlere atanabileceği veya başka fonksiyonlara argüman olarak geçirilebileceği anlamına gelir. Ayrıca, bir Dart sınıfının bir örneğini bir fonksiyon gibi çağırabilirsiniz. Detaylar için Çağrılabilir nesneleri inceleyin.

İşte bir fonksiyonu uygulamanın bir örneği:

```dart
bool gezegenMi(String gezegen) {
    return _gezegenler[gezegen] !== null;
}
```

Dart fonksiyonlar için tür açıklamalarını önerse de, fonksiyon türü dahi atlamışsanız çalışır:

```dart
gezegenMi(String gezegen) {
    return _gezegenler[gezegen] !== null;
}
```

Sadece bir ifade içeren fonksiyonlar için arrow fonksiyon kullanabilirsiniz:

```dart
bool gezegenMi(String gezegen) => return _gezegenler[gezegen] !== null;
```

`=> expr` sözdizimi, `{ return expr; }` için bir kısaltmadır. `=>` arrow fonksiyon olarak da adlandırılır.

Not: Arrow (=>) ve noktalı virgül (;) arasında sadece bir ifade —bir deyim— yer alabilir. Örneğin bir if deyimini oraya koyamazsınız, ancak bir koşullu ifade kullanabilirsiniz.

### Parametreler

Bir fonksiyonun herhangi bir sayıda zorunlu parametresi olabilir. Bu, adlandırılmış parametreler veya isteğe bağlı pozisyonel parametrelerle takip edilebilir (ancak ikisi birden değil).

### Adlandırılmış Parametreler

Adlandırılmış parametreler, açıkça zorunlu olarak işaretlenmediği sürece isteğe bağlıdır.

Bir fonksiyon tanımlarken, adlandırılmış parametreleri belirtmek için `{param1, param2, ...}` kullanın. Varsayılan bir değer sağlamaz veya adlandırılmış bir parametreyi zorunlu olarak işaretlememişseniz, türleri nullable olmalıdır, çünkü varsayılan değerleri null olacaktır:

```dart
/// [kalın] ve [gizli] bayraklarını ayarlar ...
void bayraklariEtkinlestir({bool? kalin, bool? gizli}) {...}
```

Fonksiyonu çağırırken, paramName: value kullanarak adlandırılmış argümanları belirtebilirsiniz. Örneğin:

```dart
bayraklariEtkinlestir(kalin: true, gizli: false);
```

Bir adlandırılmış parametre için varsayılan bir değer belirtmek için = kullanın. Belirtilen değer derleme zamanında bir sabit olmalıdır:

```dart
/// [kalin] ve [gizli] bayraklarını ayarlar ...
void bayraklariEtkinlestir({bool kalin = false, bool gizli = false}) {...}

// kalin true olacak; gizli false olacak.
bayraklariEtkinlestir(kalin: true);
```

Eğer adlandırılmış bir parametrenin zorunlu olmasını istiyorsanız, parametreleri required ile işaretleyebilirsiniz:

```dart
const KaydirmaCubugu({super.key, required Widget child});
```

Eğer birisi child argümanını belirtmeden bir `KaydirmaCubugu` oluşturmaya çalışırsa, analizör bir hatayı rapor eder.

Not: Zorunlu olarak işaretlenmiş bir parametre hâlâ nullable olabilir:

```dart
const KaydirmaCubugu({super.key, required Widget? child});
```

Pozisyonel argümanları önce koymak isteyebilirsiniz, Dart buna zorlama yapmaz.&#x20;

```dart
tekrar(kez: 2, () {
  ...
});
```

### İsteğe Bağlı Pozisyonel Parametreler

Fonksiyon parametrelerini \[] içine almak, onları isteğe bağlı pozisyonel parametre olarak işaretler. Varsayılan bir değer sağlamazsanız, türleri nullable olmalıdır, çünkü varsayılan değerleri null olacaktır:

```dart
String soyle(String kimden, String mesaj, [String? cihaz]) {
  var sonuc = '$kimden diyor ki $mesaj';
  if (cihaz != null) {
    sonuc = '$sonuc bir $cihaz ile gönderildi.';
  }
  return sonuc;
}
```

İsteğe bağlı parametre olmadan bu fonksiyonu çağırmak için örnek:

```dart
assert(soyle('Bayram', 'Merhaba') == 'Bayram diyor ki Merhaba');
```

Ve üçüncü parametre ile bu fonksiyonu çağırmak için örnek:

```dart
assert(soyle('Bayram', 'Merhaba', 'Android') ==
    'Bayram diyor ki Merhaba bir Android ile gönderildi.');
```

İsteğe bağlı pozisyonel bir parametre için varsayılan bir değer belirtmek için = kullanın. Belirtilen değer derleme zamanında bir sabit olmalıdır:

```dart
String soyle(String kimden, String mesaj, [String cihaz = 'telefon']) {
  var sonuc = '$kimden diyor ki $mesaj bir $cihaz ile gönderildi.';
  return sonuc;
}

assert(soyle('Bayram', 'Merhaba') == 'Bayram diyor ki Merhaba bir telefon ile gönderildi.');
```

### main() Fonksiyonu

Her uygulamanın, uygulamanın giriş noktası olarak hizmet eden bir main() fonksiyonu olmalıdır. main() fonksiyonu `void` döndürür ve opsiyonel olarak bir `List<String>` parametresi alır.

İşte basit bir main() fonksiyonu:

```dart
void main() {
  print('Merhaba, Dünya!');
}
```

İşte argümanları alan bir komut satırı uygulaması için main() fonksiyonunun bir örneği:

```dart
// Uygulamayı şu şekilde çalıştırın: dart run argumanlar.dart 1 test
void main(List<String> argumanlar) {
  print(argumanlar);

  assert(argumanlar.length == 2);
  assert(int.parse(argumanlar[0]) == 1);
  assert(argumanlar[1] == 'test');
}
```

Komut satırı argümanlarını tanımlamak ve çözmek için `args` kütüphanesini kullanabilirsiniz.

### Birinci Sınıf Fonksiyonlar

Bir fonksiyonu başka bir fonksiyona parametre olarak iletebilirsiniz. Örneğin:

```dart
void elemaniYazdir(int eleman) {
  print(eleman);
}

var liste = [1, 2, 3];

liste.forEach(elemaniYazdir);
```

Bir fonksiyonu bir değişkene atayabilirsiniz, örneğin:

```dart
var yuksekSes = (mesaj) => '!!! ${mesaj.toUpperCase()} !!!';
assert(yuksekSes('merhaba') == '!!! MERHABA !!!');
```

Bu örnek anonim bir fonksiyon kullanmaktadır. Daha fazlasını bir sonraki bölümde bulabilirsiniz.

### Anonim Fonksiyonlar

Çoğu fonksiyon adlıdır, örneğin `main()` veya `elemaniYazdir()`.  Bu fonksiyonu bir değişkene atayarak, bir koleksiyondan ekleyerek veya bir fonksiyonu çağırırken argüman olarak kullanarak bir koleksiyondan ekleyebilir veya kaldırabilirsiniz.

Anonim bir fonksiyon, parantez içinde sıfır veya daha fazla parametre, virgülle ayrılmış, opsiyonel tür açıklamaları ve parantez içinde fonksiyonun gövdesi olan bir kod bloğuna sahiptir:

```dart
([Type param1[, …]]) {
  kodBlogu;
};
```

Aşağıdaki örnek, bir listedeki her öğe için çağrılan map fonksiyonuna geçirilen bir anonim fonksiyonu tanımlar. Liste üzerinde çağrılan fonksiyon, her dizeyi büyük harfe çevirir ve ardından forEach'e geçirilen başka bir anonim fonksiyon tarafından her bir dize ve uzunluğu yazdırılır:

```dart
const liste = ['elma', 'muz', 'portakal'];
liste.map((eleman) {
  return eleman.toUpperCase();
}).forEach((eleman) {
  print('$eleman: ${eleman.length}');
});
```

Eğer fonksiyon sadece bir ifade veya return ifadesi içeriyorsa, arrow fonksiyon kullanarak bunu kısaltabilirsiniz.

```dart
liste
    .map((eleman) => eleman.toUpperCase())
    .forEach((eleman) => print('$eleman: ${eleman.length}'));
```

### Leksik Kapsam

Dart, leksik olarak kapsamlı bir dildir, bu da değişkenlerin kapsamının kodun düzenine bağlı olarak statik olarak belirlendiği anlamına gelir.&#x20;

İşte her kapsam düzeyinde değişkenlerle iç içe geçmiş fonksiyonlar içeren bir örnek:

```dart
bool ustDuzey = true;

void main() {
  var mainIc = true;

  void benimFonksiyonum() {
    var fonksiyonIc = true;

    void icIceFonksiyon() {
      var fonksiyonIcIce = true;

      assert(ustDuzey);
      assert(mainIc);
      assert(fonksiyonIc);
      assert(fonksiyonIcIce);
    }
  }
}

```

Dikkat edin ki `icIceFonksiyon()`, en üst düzeyden en alt düzeye kadar her düzeyden değişkenleri kullanabilir.

### Leksikal Kapanışlar

Bir kapanış (closure), kendi leksikal kapsamındaki değişkenlere erişimi olan bir fonksiyon nesnesidir, fonksiyon orijinal kapsamından çıkarıldığında bile. Aşağıdaki örnekte, makeAdder() fonksiyonu addBy değişkenine erişir ve döndürülen fonksiyon, addBy'yi hatırlar:

```dart
/// [miktar] değerini fonksiyonun argümanına ekleyen bir fonksiyon döndürür.
Function ekleyiciOlustur(int miktar) {
  return (int i) => miktar + i;
}

void main() {
  // 2 ekleyen bir fonksiyon oluşturun.
  var ekle2 = ekleyiciOlustur(2);

  // 4 ekleyen bir fonksiyon oluşturun.
  var ekle4 = ekleyiciOlustur(4);

  assert(ekle2(3) == 5);
  assert(ekle4(3) == 7);
}
```

### Fonksiyonların Eşitliğini Test Etme

İşte en üst seviye fonksiyonları, statik yöntemleri ve örnek yöntemleri eşitlik için test etme örneği:

```dart
void foo() {} // Bir üst seviye fonksiyon

class A {
  static void bar() {} // Bir statik yöntem
  void baz() {} // Bir örnek yöntemi
}

void main() {
  Function x;

  // Üst seviye fonksiyonları karşılaştırma.
  x = foo;
  assert(foo == x);

  // Statik yöntemleri karşılaştırma.
  x = A.bar;
  assert(A.bar == x);

  // Örnek yöntemleri karşılaştırma.
  var v = A(); // A'nın 1. örneği
  var w = A(); // A'nın 2. örneği
  var y = w;
  x = w.baz;

  // Bu kapanışlar aynı örneği (#2) referans aldığı için
  // bunlar eşittir.
  assert(y.baz == x);

  // Bu kapanışlar farklı örnekleri referans aldığı için
  // bunlar eşit değildir.
  assert(v.baz != w.baz);
}
```

Return (Dönüş) Değerleri

Tüm fonksiyonlar bir değer döndürür. Eğer belirli bir dönüş değeri belirtilmemişse, return null ifadesi otomatik olarak fonksiyon gövdesine eklenir.

```dart
foo() {}

assert(foo() == null);
```

Bir fonksiyonda birden çok değer döndürmek için, değerleri bir kayıt içinde toplayabilirsiniz.

```dart
(String, int) foo() {
  return ('bir şey', 42);
}
```

### Generators (Üreteçler)

Bir değer dizisi üretmeye ihtiyaç duyduğunuzda, bir üreteç fonksiyonu kullanmayı düşünebilirsiniz. Dart, iki tür üreteç fonksiyonunu destekler:

* Senkron üreteç: `Iterable` nesnesi döndürür.
* Asenkron üreteç: `Stream` nesnesi döndürür.

Senkron üreteç fonksiyonu uygulamak için, fonksiyon gövdesini `sync*` olarak işaretleyin ve değerleri iletmek için yield ifadelerini kullanın:

```dart
Iterable<int> dogalSayilar(int n) sync* {
  int k = 0;
  while (k < n) yield k++;
}
```

Asenkron üreteç fonksiyonu uygulamak için, fonksiyon gövdesini `async*` olarak işaretleyin ve değerleri iletmek için `yield` ifadelerini kullanın:

```dart
Stream<int> asenkronDogalSayilar(int n) async* {
  int k = 0;
  while (k < n) yield k++;
}
```

Eğer üreteciniz özyineliyse (rekürsif), `yield*` kullanarak performansını artırabilirsiniz:

```dart
Iterable<int> dogalSayilariAsagidan(int n) sync* {
  if (n > 0) {
    yield n;
    yield* dogalSayilariAsagidan(n - 1);
  }
}
```

### Harici Fonksiyonlar

Bir harici fonksiyon, gövdesi bildirimi dışında bir yerde uygulanan bir fonksiyondur. Bir fonksiyon bildiriminden önce external kelimesini ekleyin, örneğin:

```dart
external void baziFonksiyon(int i);
```

Bir harici fonksiyonun uygulaması başka bir Dart kütüphanesinden gelebilir veya daha yaygın olarak başka bir dilde yazılmış olabilir. Entegrasyon bağlamında, harici, Dart'ta kullanılabilir hale getirmek için yabancı fonksiyonlar veya değerler için tür bilgisi sağlar.

Harici fonksiyonlar, birinci düzey fonksiyonlar, örnek yöntemler, `getter`'lar veya `setter`'lar veya yönlendirici olmayan kurucular olabilir. Eğer değişken `final` değilse, bir örnek değişkeni de harici olabilir ve bu, bir harici `getter` ve (değişken `final` değilse) bir harici `setter` ile eşdeğerdir.

<br>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dart.bayramalacam.com/fonksiyonlar-functions/genel-bakis.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
