Zpět na domů

Funkcionální Rust: neměnnost a iterátory

Článek vysvětluje výhody funkcionálního stylu v Rustu: neměnnost místo mutací, deklarativní iterátory místo cyklů, explicitní zpracování chyb s Result a Option. Uvádějí se kódové příklady a doporučení pro middle/senior vývojáře.

Čistý kód v Rustu: funkcionální přístup bez mutací
Advertisement 728x90

Funkcionální styl v Rustu: neměnnost, deklarativnost a zpracování chyb

Funkcionální programování v Rustu eliminuje typické problémy imperativního a objektově orientovaného stylu: měnitelnost, imperativní cykly a implicitní zpracování chyb. Místo mutace stavů se kód staví na neměnných transformacích, deklarativních operacích a explicitních typech jako Result a Option. To dělá programy předvídatelnějšími a méně náchylnými k chybám.

Rust je ve výchozím nastavení neměnný, což nutí vývojáře přehodnotit zažité vzory. Funkcionální styl využívá iterátory, kompozici funkcí a pattern matching pro čistý kód bez vedlejších účinků.

Neměnnost místo mutace

Měnitelné proměnné vytvářejí skryté závislosti: hodnota se mění na nečekaných místech, což komplikuje ladění. V imperativním kódu může proměnná mut x změnit hodnotu kdykoli mezi deklarací a použitím.

Google AdInline article slot
fn my_function(num: i32) -> i32 {
    let mut x = num;
    // ...dalších 30 řádků...
    x += 96;
    // ...dalších 50 řádků...
    x
}

Zde se původní hodnota kazí a výsledek je nepředvídatelný kvůli možným mezilehlým změnám. Neměnnost to řeší: vytvářejí se nové hodnoty místo změny starých.

let x = 10;
let new_x = process(x); // x zůstává nezměněno

V Rustu je neměnnost normou. Pro mutaci je potřeba explicitní mut, ale funkcionální styl minimalizuje jeho použití:

  • Zkontrolujte, zda lze úlohu řešit neměnně pomocí iterátorů nebo map.
  • Pokud je mutace nevyhnutelná, izolujte ji do minimálního bloku.
  • Preferujte clone nebo borrowing pro šíření dat.

To snižuje riziko race conditions a zjednodušuje paralelismus.

Google AdInline article slot

Deklarativnost proti imperativnosti

Imperativní kód popisuje kroky provádění: cykly, podmínky, mutace. Funkcionální – požadovaný výsledek. Pro získání čtverců čísel od 0 do 9 imperativní varianta vyžaduje vektor a push:

let mut squares = Vec::new();
for num in 0..10 {
    squares.push(num * num);
}

Deklarativní využívá řetězec iterátorů:

let squares: Vec<i32> = (0..10)
    .map(|x| x * x)
    .collect();

Výhody deklarativního stylu:

Google AdInline article slot
  • Méně kódu: řetězce iterátorů nahrazují cykly.
  • Neměnnost: nedochází k mutacím kolekcí.
  • Kompozovatelnost: funkce se snadno kombinují.
  • Paralelismus: .par_iter() pro vícevláknovost bez zámků.

Iterátory v Rustu jsou líné: map se neprovede až do collect nebo for_each, což optimalizuje paměť.

Explicitní zpracování chyb

Výjimky v jiných jazycích maskují chyby: try-catch umožňuje ignorovat typy a kontext. V Rustu Result<T, E> a ? vyžadují explicitní zpracování nebo předání.

Špatný příklad s unwrap:

old_toaster().unwrap(); // Panika při chybě

Správný přístup využívá match nebo map_err:

let toast = match old_toaster() {
    Ok(t) => t,
    Err(e) => {
        eprintln!("Chyba: {}", e);
        std::process::exit(1);
    }
};

Zkratky pro zpracování:

  • match pro plnou kontrolu.
  • map_err pro transformaci chyb.
  • ? pouze pokud volající zpracuje.
  • Knihovny anyhow nebo thiserror pro pohodlí.

To zabraňuje panikám v produkci a nutí přemýšlet o chybách ve fázi kompilace.

Odstranění implicitní prázdnoty

V imperativních jazycích se null skrývá všude, což způsobuje NullPointerException. Rust používá Option<T>: Some(hodnota) nebo None explicitně.

let maybe_candies: Option<Vec<Candy>> = get_candies();
let candies = match maybe_candies {
    Some(c) => c,
    None => Vec::new(),
};

Pattern matching zaručuje zpracování obou případů. Kompilátor nepustí None.

Co je důležité

  • Neměnnost ve výchozím nastavení snižuje chyby ze stavů.
  • Iterátory a map nahrazují cykly, což dělá kód deklarativním.
  • Result a Option nutí k explicitnímu zpracování chyb a prázdnoty.
  • Kompozice funkcí zjednodušuje testování a refaktorování.
  • Funkcionální styl se hodí pro 80 % úloh v Rustu; mutace – pouze v IO nebo výkonnostních hotspotech.

— Editorial Team

Advertisement 728x90

Číst dál