8.2 KiB
Ok, ok(), is_ok(), () — rýchlokurz
1. Dva svety: Result a Option
Result<T, E> → Ok(hodnota) alebo Err(chyba)
Option<T> → Some(hodnota) alebo None
Result používaš keď chceš vedieť ČO sa pokazilo. Option keď ťa zaujíma len či niečo existuje alebo nie.
2. Čo je ()
() je "unit type" — prázdna hodnota. Znamená "nič zaujímavé".
// Funkcia, ktorá nič nevracia, v skutočnosti vracia ()
fn pozdrav() {
println!("ahoj");
}
// je to isté ako:
fn pozdrav() -> () {
println!("ahoj");
}
3. Ok(()) — úspech bez hodnoty
Keď metóda buď uspeje (ale nemá čo vrátiť) alebo zlyhá:
fn pridaj_knihu(&mut self, kniha: Kniha) -> Result<(), ()> {
if self.knihy.iter().any(|k| k.nazov == kniha.nazov) {
return Err(()); // zlyhalo — duplikát
}
self.knihy.push(kniha);
Ok(()) // úspech — ale nemám čo vrátiť, tak ()
}
Ok(()) = "podarilo sa, nemám ti čo dať".
Err(()) = "nepodarilo sa, a ani ti nepoviem prečo".
Kedy Result<(), ()>
Keď nepotrebuješ ani návratovú hodnotu ani detail chyby:
fn pridaj(&mut self, meno: &str) -> Result<(), ()> { ... }
fn nastav(&mut self, hodnota: u32) -> Result<(), ()> { ... }
Kedy Result<T, ()>
Keď pri úspechu vraciaš niečo, ale chyba nemá detail:
fn odstran(&mut self, meno: &str) -> Result<Kniha, ()> { ... }
// Ok(kniha) — tu je odstránená kniha
// Err(()) — nenašiel som ju
Kedy Result<T, String>
Keď chceš popísať chybu:
fn pridaj(&mut self, kniha: Kniha) -> Result<(), String> {
if self.knihy.iter().any(|k| k.nazov == kniha.nazov) {
return Err(format!("Kniha '{}' už existuje", kniha.nazov));
}
self.knihy.push(kniha);
Ok(())
}
4. .ok() — Result → Option (zahoď chybu)
.ok() premení Result na Option. Ak bol Err, zahodí chybu a dá None:
Result<T, E> → .ok() → Option<T>
Ok(42) → .ok() → Some(42)
Err("chyba") → .ok() → None
// Prakticky:
let cislo: Result<i32, _> = "42".parse();
let cislo: Option<i32> = "42".parse().ok(); // Some(42)
let cislo: Option<i32> = "abc".parse().ok(); // None
// Súborový I/O:
let obsah: Result<String, io::Error> = fs::read_to_string("data.json");
let obsah: Option<String> = fs::read_to_string("data.json").ok();
Kedy: Keď ťa nezaujíma detail chyby, len či sa podarilo.
5. .ok()? — najčastejší vzor na skúške
.ok() + ? spolu — premení Result na Option a ak je None, vráti None z funkcie:
fn nacitaj_zo_suboru(cesta: &PathBuf) -> Option<Kniznica> {
let raw = fs::read_to_string(cesta).ok()?;
// ^^^^^^^^^^^^^^^^^^^^^^^^^ Result<String, Error>
// .ok() → Option<String>
// ? → ak None, return None; ak Some, rozbaľ
serde_json::from_str(&raw).ok()
// ^^^ posledný riadok — .ok() premení na Option, vráti sa
}
Rozklad:
Súbor existuje:
fs::read_to_string → Ok("{ ... }")
.ok() → Some("{ ... }")
? → "{ ... }" (rozbalí Some)
serde_json::from_str → Ok(Kniznica{...})
.ok() → Some(Kniznica{...})
→ funkcia vráti Some(Kniznica{...})
Súbor neexistuje:
fs::read_to_string → Err(io::Error)
.ok() → None
? → return None (okamžite opustí funkciu)
6. .is_ok() a .is_err() — bool kontrola
let vysledok: Result<i32, String> = Ok(42);
vysledok.is_ok() // true
vysledok.is_err() // false
let vysledok: Result<i32, String> = Err("chyba".into());
vysledok.is_ok() // false
vysledok.is_err() // true
Hlavné použitie — ukladanie:
fn uloz_do_suboru(&self, cesta: &PathBuf) -> bool {
let Ok(json) = serde_json::to_string_pretty(&self) else {
return false;
};
fs::write(cesta, json).is_ok()
// ^^^^^^ Result → bool
// úspech → true, chyba → false
}
fs::write vracia Result<(), Error>. Nás zaujíma len "podarilo sa?" → .is_ok() dá bool.
7. .ok_or() a .ok_or_else() — Option → Result
Opačný smer: máš Option, chceš Result.
Option<T> → .ok_or(chyba) → Result<T, E>
Some(42) → .ok_or("nič") → Ok(42)
None → .ok_or("nič") → Err("nič")
// Prakticky — position vracia Option, ty chceš Result
fn odstran(&mut self, meno: &str) -> Result<String, ()> {
let pos = self.mena.iter().position(|m| m == meno).ok_or(())?;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Option<usize>
// .ok_or(()) → Result<usize, ()>
// ? → ak Err, return Err
Ok(self.mena.remove(pos))
}
// ok_or_else — lazy verzia (closure sa zavolá len ak None)
fn najdi(&self, meno: &str) -> Result<&Kniha, String> {
self.knihy.iter()
.find(|k| k.nazov == meno)
.ok_or_else(|| format!("Kniha '{}' nenájdená", meno))
}
8. .unwrap_or() a .unwrap_or_default() — fallback hodnota
// Option
let cislo: Option<i32> = None;
cislo.unwrap_or(0) // 0 — fallback
cislo.unwrap_or_default() // 0 — default pre i32
// Result
let cislo: Result<i32, _> = "abc".parse();
cislo.unwrap_or(0) // 0 — fallback
cislo.unwrap_or_default() // 0
// Na skúške — načítanie s fallbackom
let kniznica = Kniznica::nacitaj_zo_suboru(&cesta) // Option<Kniznica>
.unwrap_or_default(); // Kniznica::default() ak None
9. let...else — rozbaľ alebo odíď
// Ak je Ok, rozbaľ do premennej. Ak Err, vykonaj blok (musí divergovať — return/break/continue).
let Ok(json) = serde_json::to_string_pretty(&self) else {
return false;
};
// tu json je String
// Ak je Some, rozbaľ. Ak None, odíď.
let Some(kniha) = self.knihy.iter().find(|k| k.nazov == nazov) else {
return None;
};
// tu kniha je &Kniha
10. Veľký prehľad: čo kedy
Mám Result, chcem...
| Chcem | Použi | Príklad |
|---|---|---|
| Option (zahodiť chybu) | .ok() |
"42".parse().ok() → Some(42) |
| bool (podarilo sa?) | .is_ok() |
fs::write(c, d).is_ok() → true |
| Rozbaľ alebo vráť None | .ok()? |
fs::read_to_string(c).ok()? |
| Rozbaľ alebo panic | .unwrap() |
len v testoch! |
| Rozbaľ alebo fallback | .unwrap_or(val) |
vstup.parse().unwrap_or(0) |
| Rozbaľ alebo default | .unwrap_or_default() |
nacitaj().unwrap_or_default() |
| Rozbaľ alebo return | let Ok(x) = ... else { return } |
serializácia v uloz |
Mám Option, chcem...
| Chcem | Použi | Príklad |
|---|---|---|
| Result (pridať chybu) | .ok_or(err) |
vec.find(x).ok_or(()) |
| Rozbaľ alebo vráť None | ? |
slovnik.get(kat)? |
| bool (existuje?) | .is_some() / .is_none() |
mapa.get("x").is_some() |
| Rozbaľ alebo fallback | .unwrap_or(val) |
mapa.get("x").unwrap_or(&0) |
| Rozbaľ alebo default | .unwrap_or_default() |
nacitaj().unwrap_or_default() |
| Rozbaľ alebo return | let Some(x) = ... else { return } |
Chcem vrátiť z funkcie...
| Návratový typ | Úspech | Zlyhanie |
|---|---|---|
Result<(), ()> |
Ok(()) |
Err(()) |
Result<T, ()> |
Ok(hodnota) |
Err(()) |
Result<(), String> |
Ok(()) |
Err("popis".into()) |
Result<T, String> |
Ok(hodnota) |
Err(format!("...")) |
Option<T> |
Some(hodnota) |
None |
bool |
true |
false |
Konverzie — kompletná mapa
Result<T, E> ──.ok()──────→ Option<T> (zahodí E)
Result<T, E> ──.is_ok()───→ bool
Result<T, E> ──.is_err()──→ bool
Option<T> ──.ok_or(e)─────→ Result<T, E> (pridá E)
Option<T> ──.is_some()────→ bool
Option<T> ──.is_none()────→ bool
Result<T, E> ──.unwrap_or(val)────→ T
Option<T> ──.unwrap_or(val)────→ T
Result<T, E> ──.unwrap_or_default()──→ T (T: Default)
Option<T> ──.unwrap_or_default()──→ T (T: Default)