0Pricing
Learn Rust Coding · Lezione

Fn, FnMut, FnOnce

Trait delle closure

Fn, FnMut, FnOnce è una lezione Learn Rust Coding gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Learn Rust Coding, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Learn Rust Coding include 4 lezioni in totale.

I trait delle closure

Ogni closure implementa automaticamente uno o più di tre trait, in base al modo in cui usa i valori acquisiti:

  • Fn — prende in prestito in modo immutabile.
  • FnMut — prende in prestito in modo mutabile.
  • FnOnce — acquisisce la proprietà e può essere chiamata una sola volta.
fn main() {
    let x = 5;
    let show = || println!("x is {}", x); // implements Fn
    show();
    show();
}

Fn: prestito immutabile

Una closure che legge soltanto i valori catturati implementa Fn. Può essere chiamata molte volte senza modificare nulla.

fn main() {
    let greeting = String::from("Hi");
    let say = || println!("{}", greeting);
    say();
    say();
}

FnMut: prestito mutabile

Una closure che modifica un valore catturato implementa FnMut. La variabile della closure deve essere mut per poterla chiamare.

fn main() {
    let mut count = 0;
    let mut increment = || {
        count += 1;
        println!("count {}", count);
    };
    increment();
    increment();
}

FnOnce: prende la proprietà

Una closure che sposta un valore catturato fuori dall'ambiente implementa FnOnce. Può essere chiamata una sola volta.

fn main() {
    let name = String::from("Ada");
    let consume = move || {
        let owned = name;
        println!("consumed {}", owned);
    };
    consume();
}

La gerarchia dei trait

I trait formano una gerarchia:

  • Ogni Fn è anche FnMut e FnOnce.
  • Ogni FnMut è anche FnOnce.

Quindi Fn è il più flessibile e FnOnce il meno flessibile.

fn main() {
    let value = 42;
    let read = || value; // Fn, so also FnMut and FnOnce
    println!("{}", read());
}

Passare Fn alle funzioni

Una funzione può accettare una closure specificando quale trait richiede. Utilizzi i generics con un vincolo su un trait.

fn apply<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 {
    f(x)
}

fn main() {
    let double = |n| n * 2;
    println!("{}", apply(double, 9));
}

Accettare FnMut

Se la funzione deve modificare lo stato catturato, richieda FnMut e contrassegni il parametro come mut.

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

fn main() {
    let mut total = 0;
    call_twice(|| total += 1);
    // note: total is borrowed during the call
}

Accettare FnOnce

Quando una funzione chiama la closure una sola volta e può permetterle di consumare dei valori, richieda FnOnce.

fn run_once<F: FnOnce() -> String>(f: F) {
    let result = f();
    println!("{}", result);
}

fn main() {
    let s = String::from("done");
    run_once(move || s);
}

La parola chiave move

La parola chiave move obbliga una closure a prendere la proprietà delle variabili catturate invece di prenderle in prestito.

È essenziale quando una closure deve sopravvivere all'ambito in cui è stata creata, ad esempio nei thread.

fn main() {
    let data = vec![1, 2, 3];
    let printer = move || println!("{:?}", data);
    printer();
}

Come Rust sceglie il trait

Non sceglie manualmente il trait. Il compilatore decide in base al corpo della closure:

  • Legge soltanto → Fn
  • Modifica → FnMut
  • Sposta un valore catturato fuori dalla closure → FnOnce
fn main() {
    let mut log = Vec::new();
    let mut record = |x: i32| log.push(x); // FnMut
    record(1);
    record(2);
    println!("{:?}", log);
}

Scegliere il vincolo corretto

Come regola generale:

  • Accetti Fn quando deve solo chiamare e leggere.
  • Accetti FnMut quando la closure modifica lo stato.
  • Accetti FnOnce quando è sufficiente chiamarla una volta.

Scelga il vincolo più permissivo compatibile con le esigenze.

fn each<F: Fn(i32)>(items: &[i32], f: F) {
    for &i in items {
        f(i);
    }
}

fn main() {
    each(&[1, 2, 3], |n| println!("got {}", n));
}

Verifica rapida

Abbini il comportamento di una closure al trait corrispondente.

Riepilogo

I tre trait delle closure:

  • Fn — prende prestiti immutabili, può essere chiamato ripetutamente.
  • FnMut — prende prestiti mutabili, può modificare lo stato.
  • FnOnce — prende la proprietà, può essere chiamato una volta.

Il compilatore deduce il trait; move forza la cattura tramite proprietà.

fn main() {
    let base = 5;
    let adder = move |x: i32| x + base; // Fn, captures base by move
    println!("{}", adder(10));
}

Domande Frequenti

La lezione «Fn, FnMut, FnOnce» è gratuita?

Sì — il testo completo di «Fn, FnMut, FnOnce» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Learn Rust Coding, passa a CoddyKit PRO. Il corso Learn Rust Coding include 4 lezioni in totale.

Cosa imparerò in «Fn, FnMut, FnOnce»?

Trait delle closure Eserciti Learn Rust Coding con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Learn Rust Coding?

Non è richiesta alcuna esperienza precedente. Learn Rust Coding su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Fn, FnMut, FnOnce»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Learn Rust Coding?

Sì. Ogni lezione Learn Rust Coding include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Definizione delle funzioni
  2. Espressioni e istruzioni
  3. Closure
  4. Fn, FnMut, FnOnce
← Torna a Learn Rust Coding