CodeBlanks Logo Icon CodeBlanks

Summary - Error handling

Combine Result, ? and match to build a number-reading function.

Error handling summary

Expected errors are returned with Result<T, E>; bugs stop the program with panic!. ? propagates the error upward and converts it with From. To handle it on the spot, use match, if let, unwrap_or and map_err. Use unwrap/expect only where failure is impossible. Defining your own error enum for application-specific errors is a good habit.

Your own error type

Define an enum for application-specific errors; each variant is a reason for failure:

#[derive(Debug)]
enum HesapHatasi {
    Bos,
    Gecersiz(String),
}

fn ortalama(s: &str) -> Result<f64, HesapHatasi> {
    if s.trim().is_empty() {
        return Err(HesapHatasi::Bos);
    }
    // parse each piece, turn the error into Gecersiz with map_err
    todo!()
}

In later lessons you'll implement Display and std::error::Error for this type and combine it with other errors via ?.

Practice Average calculation

Complete the function fn ortalama(s: &str) -> Result<f64, HesapHatasi> with the HesapHatasi enum above: Bos for empty text; trim each comma-separated piece and convert it to f64, returning Gecersiz(piece) on error (map_err and ?). Print the results for "2,4,9", "" and "1,x" with {:?}, separated by spaces.

Starter code

main.rs
#[derive(Debug)]
enum HesapHatasi {
    Bos,
    Gecersiz(String),
}

fn main() {
    // buraya yaz
}

Sample solution

main.rs
#[derive(Debug)]
enum HesapHatasi {
    Bos,
    Gecersiz(String),
}

fn ortalama(s: &str) -> Result<f64, HesapHatasi> {
    if s.trim().is_empty() {
        return Err(HesapHatasi::Bos);
    }
    let mut toplam = 0.0;
    let mut adet = 0;
    for p in s.split(',') {
        let p = p.trim();
        let n: f64 = p.parse().map_err(|_| HesapHatasi::Gecersiz(p.to_string()))?;
        toplam += n;
        adet += 1;
    }
    Ok(toplam / adet as f64)
}

fn main() {
    println!("{:?} {:?} {:?}", ortalama("2,4,9"), ortalama(""), ortalama("1,x"));
}

Expected output

Ok(5.0) Err(Bos) Err(Gecersiz("x"))

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What is the advantage of your own error enum over String errors?

  • It always uses less memory
  • It doesn't panic
  • The compiler requires it
  • The caller can behave differently by error kind with match Correct answer

Explanation: A String can only be read; an enum lets the program decide (e.g. a default for Bos, a warning for Gecersiz).

2 Convert and propagate

Question
let n: f64 = p.parse().map_err(|_| HesapHatasi::Gecersiz(p.to_string()))____;
Answer
let n: f64 = p.parse().map_err(|_| HesapHatasi::Gecersiz(p.to_string()))?;

Explanation: map_err converts the error into your own type and ? returns it to the caller.

3 Group summary

Term Meaning
Result<T, E> Expected error
panic! Bug
? Error propagation
enum HesapHatasi Custom error type

All lessons in Beginner