Option y Result
Rust no tiene null. Un valor que podría estar ausente se envuelve en Option<T>, que es Some(value) o None — y el compilador te obliga a manejar ambos casos antes de que puedas usar el valor interior, así que un valor ausente nunca puede usarse accidentalmente como si estuviera presente.
fn find_first_even(numbers: &[i32]) -> Option<i32> {
for &n in numbers {
if n % 2 == 0 {
return Some(n);
}
}
None
}
fn main() {
let numbers = vec![1, 3, 5, 4, 7];
match find_first_even(&numbers) {
Some(n) => println!("Found: {}", n),
None => println!("No even number found"),
}
}Found: 4
Result para errores recuperables
Result<T, E> representa una operación que podría fallar: Ok(value) en caso de éxito, Err(error) en caso de fallo. Aquí no hay excepciones que lanzar ni capturar — una función que puede fallar simplemente devuelve un Result, y match obliga a quien la llama a manejar ambos resultados explícitamente.
fn divide(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err(String::from("cannot divide by zero"))
} else {
Ok(a / b)
}
}
fn main() {
match divide(10.0, 2.0) {
Ok(result) => println!("Result: {}", result),
Err(e) => println!("Error: {}", e),
}
match divide(10.0, 0.0) {
Ok(result) => println!("Result: {}", result),
Err(e) => println!("Error: {}", e),
}
}Result: 5 Error: cannot divide by zero
Siguiente: funciones — parámetros, tipos de retorno, y la sintaxis basada en expresiones de Rust.
Practice Exercise
Escribe una función first_char(s: &str) -> Option<char> que devuelva el primer carácter de s, o None si s está vacío. Llámala con "rust" y haz match del resultado, imprimiendo el carácter si es Some, o "empty" si es None.