Course contentsShow
← Rust
Lesson 825 of 1,9107. Error Handling PatternsFree lesson

Working with Result Combinators

Chain multiple operations using and_then and or_else for concise flow control.

In this lesson, you will learn how to chain multiple fallible operations together using and_then and or_else to create clean, readable error-handling flows.

The Problem with Nesting

When you perform a series of operations that might fail, you often end up with deeply nested match statements. This "pyramid of doom" makes your code hard to follow. Combinators allow us to treat the Result as a pipeline where data flows through transformations only if every step succeeds.

Chaining Success with and_then

The and_then combinator is used when you have a function that returns a Result and you want to use that result to perform another operation that also returns a Result. Think of it as a "flat map": if the first operation succeeds, and_then unwraps the value and passes it to the next function. If it fails, it skips the rest and propagates the error.

fn get_user_id(username: &str) -> Result<u32, &str> { /* ... */ }
fn fetch_data(id: u32) -> Result<String, &str> { /* ... */ }

// Chain them together cleanly
let data = get_user_id("alice")
    .and_then(fetch_data);

Providing Fallbacks with or_else

While and_then handles the "happy path," or_else handles the "recovery path." If your operation fails, or_else triggers a function that allows you to provide a fallback Result. This is perfect for when a primary source fails and you have a secondary source to try instead.

let config = read_primary_config()
    .or_else(|_| read_backup_config())
    .or_else(|_| Ok(default_config()));

Why This Matters

By using these combinators, you replace verbose match blocks with a declarative "pipeline" style. Your logic reads like a sequence of steps rather than a tree of branches. You define the flow of execution, and Rust’s Result type manages the short-circuiting logic for you—stopping automatically the moment an error occurs.

Key Takeaway: Use and_then to chain dependent operations that might fail, and use or_else to define fallback logic, keeping your error handling concise and flat.