diff --git a/priprava/rust_priprava16.md b/priprava/rust_priprava16.md new file mode 100644 index 0000000..1e2b3f5 --- /dev/null +++ b/priprava/rust_priprava16.md @@ -0,0 +1,298 @@ +# Ok, ok(), is_ok(), () — rýchlokurz + +--- + +## 1. Dva svety: Result a Option + +``` +Result → Ok(hodnota) alebo Err(chyba) +Option → 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é". + +```rust +// 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á: + +```rust +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: + +```rust +fn pridaj(&mut self, meno: &str) -> Result<(), ()> { ... } +fn nastav(&mut self, hodnota: u32) -> Result<(), ()> { ... } +``` + +### Kedy Result + +Keď pri úspechu vraciaš niečo, ale chyba nemá detail: + +```rust +fn odstran(&mut self, meno: &str) -> Result { ... } +// Ok(kniha) — tu je odstránená kniha +// Err(()) — nenašiel som ju +``` + +### Kedy Result + +Keď chceš popísať chybu: + +```rust +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: + +```rust +Result → .ok() → Option + +Ok(42) → .ok() → Some(42) +Err("chyba") → .ok() → None +``` + +```rust +// Prakticky: +let cislo: Result = "42".parse(); +let cislo: Option = "42".parse().ok(); // Some(42) +let cislo: Option = "abc".parse().ok(); // None + +// Súborový I/O: +let obsah: Result = fs::read_to_string("data.json"); +let obsah: Option = 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: + +```rust +fn nacitaj_zo_suboru(cesta: &PathBuf) -> Option { + let raw = fs::read_to_string(cesta).ok()?; + // ^^^^^^^^^^^^^^^^^^^^^^^^^ Result + // .ok() → Option + // ? → 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 + +```rust +let vysledok: Result = Ok(42); + +vysledok.is_ok() // true +vysledok.is_err() // false + +let vysledok: Result = Err("chyba".into()); + +vysledok.is_ok() // false +vysledok.is_err() // true +``` + +**Hlavné použitie — ukladanie:** + +```rust +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. + +```rust +Option → .ok_or(chyba) → Result + +Some(42) → .ok_or("nič") → Ok(42) +None → .ok_or("nič") → Err("nič") +``` + +```rust +// Prakticky — position vracia Option, ty chceš Result +fn odstran(&mut self, meno: &str) -> Result { + let pos = self.mena.iter().position(|m| m == meno).ok_or(())?; + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Option + // .ok_or(()) → Result + // ? → ak Err, return Err + Ok(self.mena.remove(pos)) +} +``` + +```rust +// 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 + +```rust +// Option +let cislo: Option = None; +cislo.unwrap_or(0) // 0 — fallback +cislo.unwrap_or_default() // 0 — default pre i32 + +// Result +let cislo: Result = "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 + .unwrap_or_default(); // Kniznica::default() ak None +``` + +--- + +## 9. let...else — rozbaľ alebo odíď + +```rust +// 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` | `Ok(hodnota)` | `Err(())` | +| `Result<(), String>` | `Ok(())` | `Err("popis".into())` | +| `Result` | `Ok(hodnota)` | `Err(format!("..."))` | +| `Option` | `Some(hodnota)` | `None` | +| `bool` | `true` | `false` | + +### Konverzie — kompletná mapa + +``` +Result ──.ok()──────→ Option (zahodí E) +Result ──.is_ok()───→ bool +Result ──.is_err()──→ bool + +Option ──.ok_or(e)─────→ Result (pridá E) +Option ──.is_some()────→ bool +Option ──.is_none()────→ bool + +Result ──.unwrap_or(val)────→ T +Option ──.unwrap_or(val)────→ T + +Result ──.unwrap_or_default()──→ T (T: Default) +Option ──.unwrap_or_default()──→ T (T: Default) +```