Presentando ?
A veces solo queremos la simplicidad de unwrap sin la posibilidad de un panic. Hasta ahora, unwrap nos ha obligado a anidar cada vez más profundamente cuando lo que realmente queríamos era obtener la variable fuera. Esto es exactamente el propósito de ?.
Al encontrar un Err, hay dos acciones válidas que se pueden tomar:
panic! que ya decidimos tratar de evitar si es posible
return porque un Err significa que no se puede manejar
? es casi[^†] exactamente equivalente a un unwrap que returns en lugar de panicar en Errs. Veamos cómo podemos simplificar el ejemplo anterior que usaba combinadores:
use std::num::ParseIntError;
fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {
let first_number = first_number_str.parse::<i32>()?;
let second_number = second_number_str.parse::<i32>()?;
Ok(first_number * second_number)
}
fn print(result: Result<i32, ParseIntError>) {
match result {
Ok(n) => println!("n es {}", n),
Err(e) => println!("Error: {}", e),
}
}
fn main() {
print(multiply("10", "2"));
print(multiply("t", "2"));
}
La macro try!
Antes de que existiera ?, la misma funcionalidad se lograba con la macro try!. Ahora se recomienda el operador ?, pero es posible que aún encuentres try! al revisar código antiguo. La misma función multiply del ejemplo anterior se vería así usando try!:
// Para compilar y ejecutar este ejemplo sin errores, mientras se usa Cargo, cambia el valor
// del campo `edition`, en la sección `[package]` del archivo `Cargo.toml`, a "2015".
use std::num::ParseIntError;
fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {
let first_number = try!(first_number_str.parse::<i32>());
let second_number = try!(second_number_str.parse::<i32>());
Ok(first_number * second_number)
}
fn print(result: Result<i32, ParseIntError>) {
match result {
Ok(n) => println!("n es {}", n),
Err(e) => println!("Error: {}", e),
}
}
fn main() {
print(multiply("10", "2"));
print(multiply("t", "2"));
}