Obliczanie stałych w Rust pozwala na wykonanie części obliczeń lub inicjalizacji na etapie kompilacji, a nie w czasie wykonywania programu.
const PI: f64 = 3.1415;
static mut GLOBAL_COUNTER: i32 = 0;
const fn to funkcja, której wynik może być użyty do nadania wartości const lub static. Takie funkcje mogą być wywoływane w kontekście stałej.
const fn factorial(n: usize) -> usize { if n == 0 { 1 } else { n * factorial(n - 1) } } const FACT_5: usize = factorial(5); // Kompiluje się!
Ograniczenia const fn:
Box::new itd.),Pytanie: Czy można używać dowolnej funkcji w kontekście const, jeśli jej wynik się nie zmienia? Na przykład w ten sposób:
fn add(a: i32, b: i32) -> i32 { a + b } const RES: i32 = add(1, 2);
Typowa błędna odpowiedź: Tak, ponieważ funkcja jest czysta, a wynik jest znany z góry.
Prawidłowa odpowiedź: Nie, funkcja musi być jawnie zadeklarowana jako const fn, tylko wtedy można ją wywołać wewnątrz inicjalizacji const. Zwykłe funkcje są wywoływane tylko w czasie wykonania!
Przykład:
const fn add(a: i32, b: i32) -> i32 { a + b } const RES: i32 = add(1, 2); // Kompiluje się!
Historia
W projekcie z obliczeniami geometrii trójwymiarowej deweloper próbował zadeklarować tabelę wartości za pomocą wyniku wywołania zwykłej funkcji, a nie const fn. W rezultacie wystąpiły błędy kompilacji, a zysk z obliczeń w czasie kompilacji został utracony.
Historia
Użycie static mut dla globalnego cache'a doprowadziło do wyścigu danych podczas dostępu z wielu wątków (static mut nie jest bezpieczny!). Konieczne było użycie Atomic lub Mutex, aby zsynchronizować dostęp do globalnego zasobu.
Historia
W próbie przyspieszenia inicjalizacji dużych tablic zadeklarowano je jako static, ale zapomniano, że static zawsze ma stały adres, przez co dane nie trafiały do cache procesora jako lokalne, a operacje spowolniły się na gorącej ścieżce logiki serwera. Należało użyć lokalnych wyrażeń let z obliczeniami w czasie wykonania.