Ç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ş: "); }
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).