Labs ICT
โญ Pro Login

Result<T, E>

Rust's way of handling errors.

What is Result<T, E>?

Rust replaces exceptions with Result<T, E>, an enum that's either Ok(value) on success or Err(error) on failure. Every function that can fail returns a Result, and the compiler forces you to handle both cases. No more unhandled exceptions crashing your program at runtime.

fn main() {
    let success: Result<i32, String> = Ok(42);
    let failure: Result<i32, String> = Err(String::from("something went wrong"));

    println!("{:?}", success);
    println!("{:?}", failure);
}
Try it Yourself ->

The ? Operator

The ? operator is Rust's secret weapon for clean error handling. If the Result is Ok, it unwraps the value. If it's Err, it returns early from the function with that error. No more match chains cluttering up your code.

use std::fs;

fn read_file(path: &str) -> Result<String, std::io::Error> {
    let content = fs::read_to_string(path)?;
    Ok(content)
}

fn main() {
    match read_file("hello.txt") {
        Ok(content) => println!("{}", content),
        Err(e) => println!("Error: {}", e),
    }
}
Try it Yourself ->

Unwrap and Expect

Just like with Option, you can use unwrap() on a Result โ€” it gives you the Ok value or panics. Use expect() instead when you want a custom panic message that explains what went wrong.

fn main() {
    let num: Result<i32, &str> = Ok(10);
    println!("{}", num.unwrap());

    let num: Result<i32, &str> = Err("bad input");
    // This would panic with message "bad input":
    // println!("{}", num.expect("failed to parse"));
}
Try it Yourself ->

Combining Results with map_err and and_then

The map_err method converts the error type, which is handy when you want to unify different error types. and_then lets you chain functions that each return a Result, keeping your error handling clean and composable.

fn main() {
    let num: Result<i32, &str> = Ok("42");

    // map_err converts the error type
    let result: Result<i32, String> = num.map_err(|e| format!("Error: {}", e));
    println!("{:?}", result);

    // and_then chains fallible operations
    let value: Result<i32, &str> = Ok(5);
    let result = value
        .and_then(|v| if v > 0 { Ok(v * 2) } else { Err("too small") })
        .and_then(|v| Ok(v + 10));
    println!("{:?}", result);
}
Try it Yourself ->

๐Ÿงช Quick Quiz

What type represents success or failure?