capypad
0 Tage Serie
rust / intermediate
Snippet

Der ? Operator: Elegante Fehlerpropagation

Der ? Operator ist syntaktischer Zucker für Fehlerpropagation, der Code prägnant und lesbar macht. Anstatt manuell auf Result-Varianten zu matchen und Fehler zurückzugeben, entpackt ? automatisch Ok-Werte und gibt Err-Werte früh aus der aktuellen Funktion zurück. In Kombination mit dem From Trait kann ? sogar automatisch zwischen Fehlertypen konvertieren—ParseIntError konvertiert automatisch zu MathError, weil wir From implementiert haben.

snippet.rs
rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
use std::num::ParseIntError;
use std::fmt;
 
#[derive(Debug)]
enum MathError {
DivisionByZero,
NegativeLogarithm,
ParseError(ParseIntError),
}
 
impl fmt::Display for MathError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
MathError::DivisionByZero => write!(f, "Division by zero"),
MathError::NegativeLogarithm => write!(f, "Logarithm of negative number"),
MathError::ParseError(ref e) => write!(f, "Parse error: {}", e),
}
}
}
 
impl From<ParseIntError> for MathError {
fn from(err: ParseIntError) -> Self {
MathError::ParseError(err)
}
}
 
fn parse_and_divide(a: &str, b: &str) -> Result<f64, MathError> {
let a_num: i32 = a.parse()?;
let b_num: i32 = b.parse()?;
if b_num == 0 { return Err(MathError::DivisionByZero); }
Ok(a_num as f64 / b_num as f64)
}
 
fn main() {
let result = parse_and_divide("10", "2");
println!("Result: {:?}", result);
}
Erklärung
1
impl From<ParseIntError> for MathError {
Ermöglicht automatische Fehlertyp-Konvertierung bei Verwendung von ?
2
let a_num: i32 = a.parse()?;
parse() gibt Result zurück; ? entpackt Ok oder gibt Err früh zurück
3
if b_num == 0 { return Err(MathError::DivisionByZero); }
Explizite Fehlerrückgabe für domänenspezifische Validierung
4
Ok(a_num as f64 / b_num as f64)
Ok-Wrapper zeigt erfolgreiche Berechnung an