Result: éxito o error como valor
En esta página
Result<T, E> es un enum con dos variantes: Result.Ok(valor) para el éxito y
Result.Err(error) para el fallo. Usar Result como tipo de retorno permite
que el compilador exija al llamador manejar ambos casos — nada queda silenciado.
Atención a la puntuación: usa punto (
.) para construir —Result.Ok(v)— y doble dos puntos (::) para casar enmatch—Result::Ok(v).
El siguiente ejemplo muestra cómo construir variantes, verificar el estado y extraer el valor de forma segura:
Constructores, is_ok / is_err, unwrap, unwrap_or y una función que retorna Result.
// Feature: Result — success or error as a value
// Syntax: `Result.Ok(v)` / `Result.Err(e)`
// When to use: functions that may fail in an expected way.
use std::Result
// `Result` is an enum with two variants:
// - `Result.Ok(value)` success
// - `Result.Err(error)` failure
let ok = Result.Ok(42)
let err = Result.Err("something went wrong")
// -- Check the variant -----------------------------------------
print(ok.is_ok()) // true
print(ok.is_err()) // false
print(err.is_ok()) // false
print(err.is_err()) // true
// -- Extract the value ----------------------------------------
print(ok.unwrap()) // 42 — panic if Err
print(err.unwrap_or(0)) // 0 — default if Err
print(err.unwrap_err()) // "something went wrong"
// -- Function that returns 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()) // true
print(r1.unwrap()) // 5
print(r2.is_err()) // true
print(r2.unwrap_err()) // division by zero
// -- Read with unwrap_or — provides a safe default ------------
print(divide(100, 4).unwrap_or(-1)) // 25
print(divide(100, 0).unwrap_or(-1)) // -1
Con match tratas ambos casos de forma exhaustiva — el compilador rechaza
código que omita una de las ramas:
match como instrucción y como expresión; enlaces con nombres descriptivos.
// Feature: Match on Result
// Syntax: `match r { Result::Ok(v) => ..., Result::Err(e) => ... }`
// When to use: handle success and failure exhaustively.
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)
}
// -- Exhaustive match ------------------------------------------
fn describe(r: Result<int, str>) {
match r {
Result::Ok(v) => print("ok: {v}"),
Result::Err(e) => print("error: {e}"),
}
}
describe(divide(10, 2))
// expected: ok: 5
describe(divide(10, 0))
// expected: error: division by zero
// Note the match syntax: `Result::Ok` (with `::`), not `.`.
// To CONSTRUCT, use `Result.Ok(v)` (with `.`).
// -- Match as expression ---------------------------------------
fn format(r: Result<int, str>) -> str {
return match r {
Result::Ok(v) => "value = {v}",
Result::Err(_) => "(failed)",
}
}
print(format(divide(10, 2))) // value = 5
print(format(divide(10, 0))) // (failed)
// -- Bindings with different names -----------------------------
let r = divide(20, 4)
match r {
Result::Ok(number) => print("computed {number}"),
Result::Err(reason) => print("failed: {reason}"),
}
// expected: computed 5
Desafío
Agrega una tercera llamada describe(divide(10, 10)) y verifica que la rama
Ok imprime ok: 1. Luego reemplaza unwrap() por unwrap_or(99) en r2
— ¿cuál es la salida?
Consulta también