Files
JR-priprava-na-skusku/priprava/rust_priprava16.md
2026-03-06 07:56:33 +01:00

299 lines
8.2 KiB
Markdown

# 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é".
```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<T, ()>
Keď pri úspechu vraciaš niečo, ale chyba nemá detail:
```rust
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:
```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<T, E> .ok() Option<T>
Ok(42) .ok() Some(42)
Err("chyba") .ok() None
```
```rust
// 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:
```rust
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
```rust
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:**
```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()``bool`.
---
## 7. .ok_or() a .ok_or_else() — Option → Result
Opačný smer: máš Option, chceš Result.
```rust
Option<T> .ok_or(chyba) Result<T, E>
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<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))
}
```
```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<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íď
```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<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)
```