fn în Rust

Declară o funcție. Tipul fiecărui parametru este obligatoriu, iar ultima expresie fără punct și virgulă este valoarea returnată.

Sintaxă
fn nume(param1: Tip1, param2: Tip2) -> TipRezultat {
    // instrucțiuni
    expresie_finala          // fără ; = valoarea returnată
}

return valoare;              // ieșire mai devreme din funcție

Ce face fn

fn declară o funcție. Fiecare parametru are tipul scris explicit (pret: f64), iar tipul rezultatului vine după ->. O funcție fără -> returnează (), tipul „unit” care înseamnă „nimic”.

În Rust, corpul funcției este un bloc, iar un bloc are valoarea ultimei expresii scrise fără ;. De aceea funcțiile scurte nu au return: fn dublu(x: i32) -> i32 { x * 2 }. Dacă pui ; după x * 2, expresia devine instrucțiune și funcția ar returna () – compilatorul dă eroare de tip.

return se folosește pentru ieșirea mai devreme, de exemplu într-o verificare la începutul funcției. Funcțiile pot fi declarate în orice ordine în fișier; nu ai nevoie de declarații înainte, ca în C.

Parametri

Parametru Descriere
nume Numele funcției, scris în snake_case (litere mici și _).
param: Tip Un parametru; tipul este obligatoriu. Poate fi și un tipar: (x, y): (i32, i32).
-> Tip Tipul valorii returnate; lipsește când funcția nu returnează nimic.

Ce returnează

Valoarea ultimei expresii din corp sau valoarea dată lui return.

Exemple

Exemplul 1: Funcție cu parametri și valoare returnată

pret_cu_tva nu are return: valoarea ei este expresia de pe ultimul rând. Funcția este folosită în main deși este declarată după ea.

fn main() {
    let pret = 100.0;
    println!("Preț fără TVA: {pret:.2} lei");
    println!("Preț cu TVA: {:.2} lei", pret_cu_tva(pret, 21.0));
}

fn pret_cu_tva(pret: f64, procent: f64) -> f64 {
    pret * (1.0 + procent / 100.0)
}

Rezultat

Preț fără TVA: 100.00 lei
Preț cu TVA: 121.00 lei

Exemplul 2: return pentru ieșire mai devreme

Dacă lista este goală, funcția iese imediat cu return None. Altfel calculează media și o returnează ca ultimă expresie.

fn media(note: &[f64]) -> Option<f64> {
    if note.is_empty() {
        return None;
    }
    let suma: f64 = note.iter().sum();
    Some(suma / note.len() as f64)
}

fn main() {
    println!("{:?}", media(&[9.0, 7.5, 10.0]));
    println!("{:?}", media(&[]));
}

Rezultat

Some(8.833333333333334)
None

Exemplul 3: Mai multe valori returnate, printr-un tuplu

O funcție returnează o singură valoare, dar aceasta poate fi un tuplu. La apel, tuplul este desfăcut direct în două variabile.

fn min_max(temperaturi: &[i32]) -> (i32, i32) {
    let mut min = temperaturi[0];
    let mut max = temperaturi[0];
    for &t in temperaturi {
        if t < min { min = t; }
        if t > max { max = t; }
    }
    (min, max)
}

fn main() {
    let (min, max) = min_max(&[12, -3, 18, 7, 21]);
    println!("Iași, săptămâna aceasta: minim {min}°C, maxim {max}°C");
}

Rezultat

Iași, săptămâna aceasta: minim -3°C, maxim 21°C

Greșeli frecvente

  • Pui ; după ultima expresie: { x * 2; }. Funcția returnează atunci (), iar compilatorul spune mismatched types și sugerează să ștergi punctul și virgula.
  • Omiți tipul unui parametru (fn dublu(x)). Rust deduce tipurile în interiorul funcțiilor, dar nu și în semnătura lor: acolo tipurile sunt obligatorii.
  • Încerci să supraîncarci o funcție (două fn arie cu parametri diferiți). Rust nu are supraîncărcare; folosește nume diferite, generics sau trait-uri.

Comenzi înrudite

  • main: Funcția cu care începe orice program Rust: este apelată automat la pornire, iar programul se termină când ea se termină.
  • closures și move: Funcții anonime, scrise cu |parametri|, care pot folosi variabilele din jur. move le dă proprietatea asupra acelor variabile.
  • generics și where: Scrii o funcție sau un tip o singură dată, pentru orice tip T; limitele (T: Trait) spun ce trebuie să știe să facă T.
  • tuple (tupluri): Grupează un număr fix de valori, de tipuri diferite, într-o singură valoare. Elementele se citesc cu .0, .1 sau prin desfacere.
  • impl, self și Self: impl adaugă metode și funcții asociate unui tip; self este valoarea pe care se apelează metoda, iar Self este tipul însuși.