gokayburuc

Rust - Closures Return Functions

Rust'ta Closure Dönen Fonksiyonlar: Fn, FnMut ve FnOnce

Konu: Closure'ları Üretip impl Trait ile Dönmek

Bu kod, bir fonksiyonun içinden closure üretip döndürmeyi ve Rust'ın üç closure trait'ini (Fn, FnMut, FnOnce) karşılaştırmayı gösteriyor.


Parça 1: Fn Dönen Üretici Fonksiyon

fn create_a_fn() -> impl Fn() {
    // Yakalanacak metin heap'te bir String olarak oluşturuluyor
    let text = "Fn".to_owned();

    // move: text closure'a sahiplikle taşınır.
    // Sonunda ; yok çünkü closure ifadesi fonksiyonun dönen değeridir.
    move || println!("This is a: {}", text)
}

Parça 2: FnMut Dönen Üretici Fonksiyon

fn create_fn_mut() -> impl FnMut() {
    let text = "FnMut".to_owned();

    // FnMut, yakaladığı durumu değiştirebilen closure'ların trait'idir
    move || println!("This is a: {}", text)
}

Parça 3: FnOnce Dönen Üretici Fonksiyon

fn create_fn_once() -> impl FnOnce() {
    let text = "FnOnce".to_owned();

    // FnOnce closure'ı çağrıldığında sahipliği tüketir; sadece bir kez çağrılabilir
    move || println!("This is a: {}", text)
}

Parça 4: Üreticileri Çağıran ve Kullanan Fonksiyon

pub fn execute_closure_output_parameter() {
    // Fn: sabit bağlamaya atanabilir, istediğin kadar çağrılabilir
    let fn_plain = create_a_fn();

    // FnMut: çağrı sırasında self'i değiştirebileceği için mut bağlama zorunlu
    let mut fn_mut = create_fn_mut();

    // FnOnce: tüketilebilir; tek çağrı sonrası artık kullanılamaz
    let fn_once = create_fn_once();

    fn_plain(); // "This is a: Fn"
    fn_mut();   // "This is a: FnMut"
    fn_once();  // "This is a: FnOnce"
}

Çıktı

This is a: Fn
This is a: FnMut
This is a: FnOnce

Özet ve Sonuç

Parça Dönen Trait Bağlama Kaç kez çağrılabilir
create_a_fn Fn let Sınırsız
create_fn_mut FnMut let mut Sınırsız (mutabıl)
create_fn_once FnOnce let Yalnızca bir kez

Parçalar arası ilişki ve veri akışı:

  1. Her üretici fonksiyon kendi yerel String'ini oluşturur ve move ile ürettiği closure'ın sahipliğine devreder. Fonksiyon döndüğünde text düşmez, çünkü artık sahibi closure'dır — bu, move'un varlık sebebidir.
  2. impl Fn()/FnMut()/FnOnce() imzaları, isimsiz closure tiplerini soyutlayarak çağıran tarafa tip bilgisi olmadan erişim imkânı sunar.
  3. execute_closure_output_parameter üçünü de bağlar ve çağırır; mut zorunluluğu ile tek kullanımlık kısıtı, trait hiyerarşisinin (Fn ⊂ FnMut ⊂ FnOnce) doğal sonucudur.

Öğrenilecek ana ders: Kısıtlayıcı trait'i seçmek API sözleşmesini belirler. FnOnce dönmek esnekliği azaltır, Fn dönmek en kullanışlısıdır; closure'ınız mümkünse derleyici bunu otomatik olarak en kısıtlayıcı uygun trait'e atar. Kod okunurluğu açısından, gerçekten durum değiştirmeyen closure'lar için Fn imzası tercih edilmelidir — bu örnek eğitim amaçlı olarak üçünü de ayrı ayrı gösterir.

#rust