CodeBlanks Logo Icon CodeBlanks

Fn, FnMut, FnOnce

Üç closure trait'ini ve farklarını ayırt edersin.

Fn, FnMut, FnOnce

Closure'lar yakalama biçimlerine göre üç trait'ten birini (ya da birkaçını) uygular:

  • FnOnce — en az bir kez çağrılabilir; yakaladığını tüketebilir.
  • FnMut — birçok kez çağrılabilir, yakaladığını değiştirebilir.
  • Fn — birçok kez çağrılabilir, yalnızca okur.
fn uygula<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 { f(x) }
fn iki_kez<F: FnMut()>(mut f: F) { f(); f(); }
fn bir_kez<F: FnOnce() -> String>(f: F) -> String { f() }

Her Fn aynı zamanda FnMut, her FnMut aynı zamanda FnOnce'dır.

Doğru sınırı seçmek

Fonksiyonun closure ile ne yapacağına göre sınır seçilir:

let mut n = 0;
iki_kez(|| n += 3);                // FnMut: n'yi değiştirir
println!("{n}");                   // 6

let s = String::from("son");
println!("{}", bir_kez(move || s));   // FnOnce: s'yi döndürüp tüketir
println!("{}", uygula(|x| x + 10, 5)); // Fn: 15

iki_kez'e move || s verilemez; s ikinci çağrıda artık yoktur.

Uygulama Üç trait

Yukarıdaki uygula, iki_kez ve bir_kez fonksiyonlarını yaz. uygula(|x| x + 10, 5), iki kez 3 eklenmiş n ve bir_kez(move || s) (s = "son") sonuçlarını boşlukla yazdır.

Başlangıç kodu

main.rs
fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
fn uygula<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 {
    f(x)
}

fn iki_kez<F: FnMut()>(mut f: F) {
    f();
    f();
}

fn bir_kez<F: FnOnce() -> String>(f: F) -> String {
    f()
}

fn main() {
    let a = uygula(|x| x + 10, 5);
    let mut n = 0;
    iki_kez(|| n += 3);
    let s = String::from("son");
    let c = bir_kez(move || s);
    println!("{} {} {}", a, n, c);
}

Beklenen çıktı

15 6 son

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Parametre olarak closure alırken hangi sınır en esnek olanıdır (en çok closure'ı kabul eder)?

  • FnOnce Doğru cevap
  • Fn
  • FnMut
  • Hepsi eşit

Açıklama: Her closure FnOnce'tır. Ancak fonksiyon closure'ı birden çok kez çağıracaksa FnMut ya da Fn istemelidir.

2 Değiştiren closure sınırı

Soru
fn iki_kez<F: ____()>(mut f: F) {
    f();
    f();
}
Cevap
fn iki_kez<F: FnMut()>(mut f: F) {
    f();
    f();
}

Açıklama: Birden çok kez çağrılıp durumu değiştirebilen closure FnMut ister.

3 Closure ve uyguladığı en dar trait

Kavram Anlamı
|x| x + 10 Fn
|| n += 3 FnMut
move || s (String döner) FnOnce
|| println!("{x}") Fn (okur)

Orta seviye bölümündeki tüm dersler