Çevreleyici özellikleri (Closure traits)

Çevreleyicilerin (closures) veya lambda ifadelerinin isimlendirilemeyen türleri vardır. Ancak, özel Fn, FnMut ve FnOnce özelliklerini (traits) gerçekleştirirler (implement):

Özel fn(..) -> T türleri, fonksiyon göstericilerine (function pointers) referans verir - ya bir fonksiyonun adresi ya da hiçbir şey yakalamayan (capture) bir çevreleyici (closure).

fn apply_and_log(
    func: impl FnOnce(&'static str) -> String,
    func_name: &'static str,
    input: &'static str,
) {
    println!("Çağrılıyor {func_name}({input}): {}", func(input))
}

fn main() {
    let suffix = "sendromu";
    let add_suffix = |x| format!("{x} {suffix}");
    apply_and_log(&add_suffix, "add_suffix", "son sınıf");
    apply_and_log(&add_suffix, "add_suffix", "apandis");

    let mut v = Vec::new();
    let mut accumulate = |x| {
        v.push(x);
        v.join("/")
    };
    apply_and_log(&mut accumulate, "accumulate", "kırmızı");
    apply_and_log(&mut accumulate, "accumulate", "yeşil");
    apply_and_log(&mut accumulate, "accumulate", "mavi");

    let take_and_reverse = |prefix| {
        let mut acc = String::from(prefix);
        acc.push_str(&v.into_iter().rev().collect::<Vec<_>>().join("/"));
        acc
    };
    apply_and_log(take_and_reverse, "take_and_reverse", "ters çevrilmiş: ");
}
This slide should take about 10 minutes.

Bir Fn (ör. add_suffix) yakalanan değerleri (captured values) ne tüketir ne de değiştirir. Sadece çevreleyiciye (closure) paylaşılan bir referans (shared reference) gerektirerek çağrılabilir, bu da çevreleyicinin tekrar tekrar ve hatta eş zamanlı olarak (concurrently) yürütülebileceği anlamına gelir.

Bir FnMut (ör. accumulate) yakalanan değerleri (captured values) değiştirebilir. Çevreleyici (closure) nesnesine özel (exclusive) referans yoluyla erişilir, bu nedenle tekrar tekrar çağrılabilir ancak eş zamanlı olarak (concurrently) çağrılamaz.

Eğer bir FnOnce’ınız varsa (ör. take_and_reverse), onu yalnızca bir kez çağırabilirsiniz. Bunu yapmak, çevreleyiciyi (closure) ve taşıma (move) ile yakalanan tüm değerleri tüketir.

FnMut, FnOnce’ın bir alt türüdür. Fn, FnMut ve FnOnce’ın bir alt türüdür. Yani, FnOnce’ın istendiği her yerde bir FnMut kullanabilirsiniz ve FnMut veya FnOnce’ın istendiği her yerde bir Fn kullanabilirsiniz.

Bir çevreleyici (closure) alan bir fonksiyon tanımladığınızda, yapabiliyorsanız FnOnce (yani onu bir kez çağırırsınız), değilse FnMut ve son olarak Fn almalısınız. Bu, çağırana (caller) en fazla esnekliği sağlar.

Buna karşılık, bir çevreleyiciniz (closure) olduğunda, sahip olabileceğiniz en esnek olan Fn’dir (3 çevreleyici özelliğinin (trait) herhangi birinin tüketicisine geçirilebilir), sonra FnMut ve son olarak FnOnce.

Derleyici ayrıca, çevreleyicinin (closure) ne yakaladığına bağlı olarak Copy (ör. add_suffix için) ve Clone (ör. take_and_reverse) çıkarımı yapar (infers). Fonksiyon göstericileri (fn öğelerine referanslar) Copy’yi ve Fn’yi gerçekleştirir (implement).