Combinadores de Result
En esta página
Los combinadores permiten componer operaciones sobre Result sin necesidad de
match o unwrap intermedios. Cada método recibe un closure y devuelve un
nuevo Result:
| Método | Cuándo usar |
|---|---|
.map(f) |
Transforma el valor Ok; Err pasa sin modificarse |
.map_err(f) |
Transforma el error; Ok pasa sin modificarse |
.and_then(f) |
Encadena una operación que también retorna Result |
.or_else(f) |
Intenta recuperarse de un Err |
map, map_err, and_then, or_else y un pipeline completo encadenado.
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_thense detiene en el primer fallo — útil para pipelines donde cada etapa depende del éxito de la anterior..or_elsehace lo contrario: recupera el flujo cuando hay un error.
Desafío
Agrega un segundo .and_then al pipeline que rechace valores mayores que 100.
¿Qué ocurre con pipeline(500)?
Consulta también