Ir al contenido

Option en Rust

Rust no tiene null. Si un valor puede faltar, eso se dice directamente en el tipo, usando Option. Al principio parece un trámite de más, pero elimina una categoría entera de errores: la famosa “referencia nula”, que ha provocado incontables fallos en otros lenguajes.

Option es un enum con dos variantes:

enum Option<T> {
Some(T), // hay un valor
None, // no hay valor
}

De hecho, ya lo has visto: .get() en un vector y .get() en un HashMap devuelven un Option.

fn main() {
let has_value: Option<i32> = Some(5);
let no_value: Option<i32> = None;
println!("{:?}", has_value);
println!("{:?}", no_value);
}

Salida:

Some(5)
None
▶ Pruébalo tú mismo

La forma segura de sacar el valor es con match. Rust te obliga a cubrir los dos casos, así que no puedes olvidarte sin querer del caso en el que falta el valor:

fn main() {
let age: Option<i32> = Some(30);
match age {
Some(value) => println!("La edad es {value}"),
None => println!("No se indicó la edad"),
}
}
▶ Pruébalo tú mismo
fn find_user(id: u32) -> Option<&'static str> {
if id == 1 {
Some("Alice")
} else {
None
}
}
fn main() {
match find_user(1) {
Some(name) => println!("Encontrado: {name}"),
None => println!("Usuario no encontrado"),
}
match find_user(99) {
Some(name) => println!("Encontrado: {name}"),
None => println!("Usuario no encontrado"),
}
}

Salida:

Encontrado: Alice
Usuario no encontrado
▶ Pruébalo tú mismo

En lugar de devolver null o lanzar una excepción cuando no encuentra al usuario, es el propio tipo de retorno de la función el que avisa a quien la llama: “puede que no encuentre nada”. Y el compilador no le deja ignorar esa posibilidad.

En los casos sencillos, un match completo puede parecer demasiado. Hay un par de atajos:

fn main() {
let age: Option<i32> = None;
let value = age.unwrap_or(0); // si no hay valor, usa 0
println!("{value}");
}
▶ Pruébalo tú mismo

También existe .unwrap(), que te da el valor directamente, pero provoca un panic (el programa se detiene) si es None:

let age: Option<i32> = Some(30);
let value = age.unwrap(); // aquí no hay problema, porque age es Some

Escribe fn first_even(numbers: &[i32]) -> Option<i32>, que devuelva el primer número par del slice, o None si no hay ninguno. Imprime el resultado para [3, 7, 8, 10] con match, y para [1, 3, 5] con .unwrap_or(0). Pista: recorre el slice y haz return Some(n) en cuanto n % 2 == 0; después del bucle, devuelve None.

Ver solución
fn first_even(numbers: &[i32]) -> Option<i32> {
for &n in numbers {
if n % 2 == 0 {
return Some(n);
}
}
None
}
fn main() {
match first_even(&[3, 7, 8, 10]) {
Some(n) => println!("Primer par: {n}"),
None => println!("No hay números pares"),
}
let fallback = first_even(&[1, 3, 5]).unwrap_or(0);
println!("Con valor por defecto: {fallback}");
}

Salida:

Primer par: 8
Con valor por defecto: 0
▶ Pruébalo tú mismo

Crea un HashMap de ajustes que solo contenga "volumen" con el valor 80. Después recorre las claves "volumen" y "brillo" e imprime el valor si existe, o un mensaje de “no configurado” si no existe. Pista: .get(key) sobre un HashMap devuelve un Option, así que puedes usar match directamente sobre él.

Ver solución
use std::collections::HashMap;
fn main() {
let mut settings = HashMap::new();
settings.insert("volumen", 80);
for key in ["volumen", "brillo"] {
match settings.get(key) {
Some(value) => println!("{key} = {value}"),
None => println!("{key} no está configurado"),
}
}
}

Salida:

volumen = 80
brillo no está configurado
▶ Pruébalo tú mismo
  • Option<T> representa un valor que puede estar o no estar. Rust no tiene null.
  • Some(value) contiene algo; None significa que no hay nada.
  • match es la forma segura de manejar los dos casos: el compilador no te deja olvidar ninguno.
  • .unwrap_or(default) te da un valor de respaldo; .unwrap() provoca un panic si el valor es None, así que úsalo con moderación.

Comprueba lo aprendido

1. ¿Qué usa Rust en lugar de null para un valor que puede faltar?

2. ¿Qué pasa si llamas a .unwrap() sobre un valor None?

3. ¿Qué hace age.unwrap_or(0) cuando age es None?

4. ¿Por qué match se considera la forma segura de sacar el valor de un Option?

5. ¿Cuáles de los métodos mencionados en esta página ya devuelven un Option?

Puntuación: 0 / 5