In Rust, cos'è `fn () -> ()`?
Ho una conoscenza dei tratti Fn (capitale-F): Fn, FnMut, FnOnce. Capisco che sono tratti e funzionano come tratti.
Ma per quanto riguarda fn(f minuscola)? Ha una colorazione diversa negli editor, il che mi dice che non è un tratto. Può essere utilizzato anche in alcuni luoghi in cui gli altri non possono (e viceversa), sebbene sembri comportarsi in modo simile in altri casi. Non sono riuscito a trovare nulla che lo spieghi direttamente nei documenti.
Risposte
La risposta di prog-fh è essenzialmente corretta, ma manca di qualche sfumatura. Rust ha tre tipi di tipi di funzioni:
Gli elementi funzione sono ciò che ottieni quando crei una funzione utilizzando
fn foo() {...}. È anche il tipo del costruttore di una struttura tipo tupla o di una variante enum. Gli elementi funzione sono di dimensione zero (non contengono dati) e ogni funzione non generica ha un tipo di elemento funzione univoco e non nominabile. Nei messaggi di errore, il compilatore mostra questi "tipi Voldemort" come qualcosa di similefn() -> () {foo}(con il nome della funzione in{}).Le chiusure sono valori simili agli elementi funzione, ma le chiusure possono contenere dati: copie o riferimenti a qualsiasi variabile catturata dal loro ambiente. Come già sai, crei una chiusura utilizzando la sintassi di chiusura (
|args| expression). Come gli elementi funzione, le chiusure hanno tipi unici e non nominabili (resi dal compilatore qualcosa di simile[closure@src/main.rs:4:11: 4:23]).I puntatori a funzione sono ciò che stai chiedendo: i tipi che assomigliano
fn() -> (). I puntatori a funzione non possono contenere dati, ma non sono di dimensione zero; come suggerisce il nome, sono dei puntatori. Un puntatore a funzione può puntare a un elemento di funzione oa una chiusura che non acquisisce nulla, ma non può essere nullo.
Gli elementi funzione e le chiusure vengono automaticamente forzate al tipo di puntatore a funzione pertinente quando possibile, ecco perché let f: fn(i32) = |_| ();funziona: poiché la chiusura non cattura nulla, può essere forzata a un puntatore a funzione.
Funzione-come tutti e tre i tipi di attuare le pertinenti Fn, FnMute FnOncetratti (a parte che le chiusure potrebbero non implementare Fno FnMutseconda di ciò che la cattura). Voci delle funzioni e puntatori a funzione anche implementare Copy, Clone, Sende Sync(chiusure implementare solo questi tratti quando tutti i loro contenuti fanno).
Dal punto di vista delle prestazioni, i puntatori a funzione sono una sorta di compromesso tra generici e oggetti tratto. Devono essere dereferenziati per essere chiamati, quindi chiamare un puntatore a funzione potrebbe essere più lento rispetto a chiamare un elemento funzione o una chiusura direttamente, ma comunque più veloce di chiamare un dyn Fnoggetto tratto, che implica una ricerca vtable oltre alla chiamata indiretta.
Riferimenti
- Qual è la differenza pratica tra l'elemento fn e il puntatore fn?
- Perché progettare una lingua con tipi anonimi unici?
- Come faccio a creare una struttura per FFI che contiene un puntatore a funzione nullable?
- Perché il passaggio di una chiusura a una funzione che accetta un puntatore a funzione non funziona?
È un tipo di puntatore a funzione .
Si riferisce solo a una funzione, non a una chiusura, poiché contiene solo l'indirizzo della funzione e non l'ambiente catturato di cui una chiusura ha bisogno.
Un Fntratto (F maiuscola) può riferirsi a una chiusura oa una funzione.
fn è il tipo per un puntatore a funzione. Vedi anche qui nella documentazione:https://doc.rust-lang.org/std/primitive.fn.html