La valutazione delle costanti in Rust consente di eseguire alcune operazioni di calcolo o inizializzazione durante la fase di compilazione, anziché durante l'esecuzione del programma.
const PI: f64 = 3.1415;
static mut GLOBAL_COUNTER: i32 = 0;
const fn è una funzione il cui risultato può essere utilizzato per impostare il valore di const o static. Queste funzioni possono essere chiamate in un contesto costante.
const fn factorial(n: usize) -> usize { if n == 0 { 1 } else { n * factorial(n - 1) } } const FACT_5: usize = factorial(5); // Compila!
Limitazioni di const fn:
Box::new e simili),Domanda: È possibile utilizzare qualsiasi funzione in un contesto const, se il suo risultato non cambia? Ad esempio, in questo modo:
fn add(a: i32, b: i32) -> i32 { a + b } const RES: i32 = add(1, 2);
Risposta tipica errata: Sì, poiché la funzione è pura e il risultato è noto in anticipo.
Risposta corretta: No, la funzione deve essere esplicitamente dichiarata come const fn, solo allora può essere chiamata all'interno dell'inizializzazione const. Le funzioni normali vengono chiamate solo durante l'esecuzione!
Esempio:
const fn add(a: i32, b: i32) -> i32 { a + b } const RES: i32 = add(1, 2); // Compila!
Storia
In un progetto di calcoli di geometria tridimensionale, uno sviluppatore ha tentato di dichiarare una tabella di valori tramite il risultato di una chiamata a una funzione normale, invece che a una const fn. Di conseguenza, sono emersi errori di compilazione e il vantaggio del calcolo a compile-time è stato perso.
Storia
L'uso di static mut per una cache globale ha portato a condizioni di gara durante l'accesso da più thread (static mut non è sicuro!). Era necessario utilizzare Atomic o Mutex per sincronizzare l'accesso alla risorsa globale.
Storia
Nel tentativo di accelerare l'inizializzazione di grandi array, sono stati definiti come statici, ma si è dimenticato che static ha sempre un indirizzo fisso, il che ha portato a una mancata memorizzazione nella cache della CPU come locale, rallentando le operazioni sul percorso caldo della logica del server. Era necessario utilizzare espressioni let locali con calcoli a runtime.