Combinadores de Result
Nesta página
Combinadores permitem compor operações sobre Result sem precisar de match
ou unwrap intermediário. Cada método recebe uma closure e devolve um novo
Result:
| Método | Quando usar |
|---|---|
.map(f) |
Transforma o valor Ok; Err passa sem toque |
.map_err(f) |
Transforma o erro; Ok passa sem toque |
.and_then(f) |
Encadeia uma operação que também retorna Result |
.or_else(f) |
Tenta se recuperar de um Err |
map, map_err, and_then, or_else e um pipeline completo encadeado.
04-result-combinators.zolo
// Feature: Result combinators — map, map_err, and_then, or_else
// Syntax: `r.map(fn)`, `r.map_err(fn)`, `r.and_then(fn)`, `r.or_else(fn)`
// When to use: transform/recover without unwrapping.
use std::Result
fn divide(a: int, b: int) -> Result<int, str> {
if b == 0 {
return Result.Err("division by zero")
}
return Result.Ok(a / b)
}
// -- map: transforms the Ok value, leaves Err passthrough -----
let r1 = divide(10, 2).map(|v| v * 10)
print(r1.unwrap()) // 50
let r2 = divide(10, 0).map(|v| v * 10)
print(r2.is_err()) // true (map didn't touch the error)
// -- map_err: transforms the error, leaves Ok passthrough -----
let r3 = divide(10, 0).map_err(|e| "math: {e}")
print(r3.unwrap_err()) // math: division by zero
let r4 = divide(10, 2).map_err(|e| "ignored: {e}")
print(r4.unwrap()) // 5 (map_err doesn't touch Ok)
// -- and_then: chains an operation that returns Result --------
fn safe_double(n: int) -> Result<int, str> {
if n > 1000 {
return Result.Err("overflow")
}
return Result.Ok(n * 2)
}
let r5 = divide(20, 4).and_then(safe_double)
print(r5.unwrap()) // 10
// Err stops the chain at the first error:
let r6 = divide(20, 0).and_then(safe_double)
print(r6.is_err()) // true (safe_double was never called)
// -- or_else: recovers from Err -------------------------------
let r7 = divide(10, 0).or_else(|_| Result.Ok(0))
print(r7.unwrap()) // 0
let r8 = divide(10, 2).or_else(|_| Result.Ok(999))
print(r8.unwrap()) // 5 (Ok passes through)
// -- Full pipeline --------------------------------------------
fn pipeline(x: int) -> Result<int, str> {
return divide(x, 2).and_then(safe_double).map(|v| v + 1)
}
print(pipeline(10).unwrap()) // (10/2)*2 + 1 = 11
print(pipeline(0).unwrap()) // 0/2=0, *2=0, +1 = 1
.and_thenpara na primeira falha — útil para pipelines em que cada etapa depende do sucesso da anterior..or_elsefaz o inverso: recupera o fluxo quando há um erro.
Desafio
Adicione um segundo .and_then ao pipeline que rejeite valores maiores
que 100. O que acontece com pipeline(500)?
Veja também