Saltar al contenido

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
Playground
// 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_then se detiene en el primer fallo — útil para pipelines donde cada etapa depende del éxito de la anterior. .or_else hace 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)?

Buscar en Zolo

9 resultados

enespt-br