Resultado (std::Result)
En esta página
std::Result representa un éxito (Result.Ok(valor)) o un
fallo (Result.Err(mensaje)). Las funciones que pueden fallar retornan un
Result en lugar de lanzar excepciones — el llamador decide cómo reaccionar.
Ok y Err
Los dos constructores y los predicados is_ok / is_err:
Función divide que retorna Ok o Err según el divisor.
// Feature: Result.Ok / Result.Err — the two variants of the type
// When to use: representing success or failure without using exceptions.
use std::Result
let ok = Result.Ok(42)
let err = Result.Err("failed")
// is_ok / is_err — quick checks.
print(ok.is_ok()) // expected: true
print(ok.is_err()) // expected: false
print(err.is_ok()) // expected: false
print(err.is_err()) // expected: true
// Function that returns a Result.
fn divide(a: int, b: int) -> Result<int, str> {
if b == 0 {
return Result.Err("division by zero")
}
return Result.Ok(a / b)
}
let r1 = divide(10, 2)
let r2 = divide(10, 0)
print(r1.is_ok()) // expected: true
print(r2.is_err()) // expected: true
Unwrap
unwrap() extrae el valor de un Ok — entra en pánico si es Err. Usa
unwrap_or(default) para proporcionar un fallback seguro:
unwrap_or nunca entra en pánico; unwrap_err extrae el mensaje de error.
// Feature: .unwrap / .unwrap_or / .unwrap_err — extracting the value
// When to use: pulling the inner value; unwrap_or avoids panic on Err.
use std::Result
let ok = Result.Ok(42)
let err = Result.Err("oops")
// unwrap — returns the value; PANICS on Err.
print(ok.unwrap()) // expected: 42
// unwrap_or — safe default when Err.
print(err.unwrap_or(0)) // expected: 0
print(ok.unwrap_or(999)) // expected: 42
// unwrap_err — returns the error; PANICS on Ok.
print(err.unwrap_err()) // expected: oops
// Safe pattern: test first.
fn show(r: Result<int, str>) {
if r.is_ok() {
print("ok: {r.unwrap()}")
} else {
print("err: {r.unwrap_err()}")
}
}
show(Result.Ok(10)) // expected: ok: 10
show(Result.Err("failure")) // expected: err: failure
Map
map transforma el valor interno de un Ok sin salir del Result. Un Err
pasa sin ser tocado. map_err hace lo mismo para el lado del error:
Encadenamiento de map para múltiples transformaciones.
// Feature: Result.map / Result.map_err — transform within a Result
// When to use: applying a transformation to the value without unwrapping.
use std::Result
let ok = Result.Ok(10)
let err = Result.Err("failure")
// map — transforms the inner value when Ok; passes Err through unchanged.
let doubled = ok.map(|x| x * 2)
print(doubled.unwrap()) // expected: 20
let still_err = err.map(|x| x * 2)
print(still_err.is_err()) // expected: true
print(still_err.unwrap_err()) // expected: failure
// map_err — transforms the error when Err; passes Ok through unchanged.
let prefixed = err.map_err(|e| "ERROR: " + e)
print(prefixed.unwrap_err()) // expected: ERROR: failure
let ok2 = ok.map_err(|e| "never")
print(ok2.unwrap()) // expected: 10
// Chain map for multiple transformations.
let r = Result.Ok(5)
let r2 = r.map(|x| x + 1)
let r3 = r2.map(|x| x * 10)
print(r3.unwrap()) // expected: 60
And Then
and_then encadena operaciones que ellas mismas retornan un Result. El
primer Err interrumpe la cadena y se propaga:
Dos pasos que pueden fallar; and_then elimina la verificación manual.
// Feature: Result.and_then — chain operations that return a Result
// When to use: pipelines with multiple failing steps; each callback
// returns a fresh Result.
use std::Result
fn parse_int(s: str) -> Result<int, str> {
if s == "1" { return Result.Ok(1) }
if s == "2" { return Result.Ok(2) }
if s == "3" { return Result.Ok(3) }
return Result.Err("parse error: {s}")
}
fn double_if_even(n: int) -> Result<int, str> {
if n % 2 == 0 {
return Result.Ok(n * 2)
}
return Result.Err("not even: {n}")
}
// Happy path — all Ok.
let r1 = parse_int("2").and_then(double_if_even)
print(r1.is_ok()) // expected: true
print(r1.unwrap()) // expected: 4
// Failure in the 1st step — Err propagates.
let r2 = parse_int("z").and_then(double_if_even)
print(r2.is_err()) // expected: true
// Failure in the 2nd step.
let r3 = parse_int("1").and_then(double_if_even)
print(r3.is_err()) // expected: true
print(r3.unwrap_err()) // expected: not even: 1
El Operador ?
? tras una expresión Result extrae el Ok o retorna inmediatamente
el Err al llamador — equivalente a if is_err { return } sin el ruido:
add con ? vs. add_v1 sin ? — idénticos en comportamiento, diferentes en claridad.
// Feature: The `?` operator — propagates Err automatically
// When to use: clean code in pipelines; equivalent to if-let-Err-return.
use std::Result
fn parse_int(s: str) -> Result<int, str> {
if s == "10" { return Result.Ok(10) }
if s == "5" { return Result.Ok(5) }
return Result.Err("parse: {s}")
}
// Without `?`: every call needs to be checked manually.
fn add_v1(a: str, b: str) -> Result<int, str> {
let ra = parse_int(a)
if ra.is_err() { return ra }
let rb = parse_int(b)
if rb.is_err() { return rb }
return Result.Ok(ra.unwrap() + rb.unwrap())
}
// With `?`: each `?` extracts the Ok or returns the Err immediately.
fn add(a: str, b: str) -> Result<int, str> {
let x = parse_int(a)?
let y = parse_int(b)?
return Result.Ok(x + y)
}
// Happy path.
let r1 = add("10", "5")
print(r1.unwrap()) // expected: 15
// Failure — first Err propagates.
let r2 = add("oops", "5")
print(r2.is_err()) // expected: true
print(r2.unwrap_err()) // expected: parse: oops
// Failure on the second call.
let r3 = add("10", "xyz")
print(r3.unwrap_err()) // expected: parse: xyz
// Both versions are equivalent.
print(add_v1("10", "5").unwrap()) // expected: 15
Desafío
Escribe una función sqrt_positive(n: int) -> Result<float, str> que retorne
Err cuando n < 0 y Ok(sqrt(n)) en caso contrario. Luego compónla con
and_then para calcular la suma de dos raíces cuadradas.
Consulta también