liveBook · Manning

Result type

As explained in Idiomatic Rust

Result is Rust's standard-library enum representing either successful output of type T or an error of type E.

`Result<T, E>` represents either a successful value, `Ok(T)`, or an error, `Err(E)`. It lets a caller decide what to do when an operation fails instead of burying the failure inside the operation. section 3.1.2

Use `match` when success and failure need different responses. When a function should pass an error to its caller, `?` keeps a sequence of fallible calls flat: it continues with an `Ok` value or returns early on `Err`. The enclosing function must return a compatible `Result`; error types must match or be convertible through `From`. A successful function with no value to return can finish with `Ok(())`. section 3.1.2

fn write_to_file() -> std::io::Result<()> {  #1
    use std::fs::File; #2
    use std::io::prelude::*; #2

    let mut file = File::create("filename")?;  #2
    file.write_all(b"File contents")?;        
    Ok(())                                   #3
}
fn try_to_write_to_file() {
    match write_to_file() {      #4
        Ok(()) => println!("Write succeeded"),
        Err(err) => println!("Write failed: {}", err.to_string()),
    }
}

File creation and writing each use `?` to propagate an I/O error; the caller matches on the final `Result` to report success or failure. section 3.1.2

If the caller needs a richer error, define an error type and implement `From` for errors produced by the calls. `map_err()` can transform an error directly; `ok()` and `err()` convert a `Result` to an `Option`, while `ok_or()` converts an `Option` to a `Result`. section 3.1.2

Keep or discard parsing failures

Parsing strings produces `Result` values. `flat_map()` uses `Result::into_iter()` to retain `Ok` values and silently discard `Err` values. If failures matter, partition the results with `Result::is_ok` instead; the two collections can then be inspected separately. Avoid flattening merely to make errors disappear. section 3.2.5

let arr = ["duck", "1", "2", "goose", "3", "4"];
let (successes, failures): (Vec<_>, Vec<_>) = arr
    .iter()
    .map(|v| v.parse::<i32>())
    .partition(Result::is_ok);
println!("successses={:?}", successes);
println!("failures={:?}", failures);

The parsing pipeline retains both successful integers and invalid-digit errors as `Result` values in separate vectors. section 3.2.5

How Idiomatic Rust covers it

How deep it goes
Works through matching, `?`, error conversion, and iterator handling; does not examine the enum’s implementation.
Examples
Shows file creation and writing, custom error wrapping, and partitioning parsed strings into successes and failures.
What it assumes
Assumes familiarity with Rust functions, types, and iterators; explains `?` and the unit return value in context.
What you can do after
Apply it via `?` and `match` to handle failures, and use `partition()` when parsing errors must remain visible.
How it connects
Connects `Result` to `Option`, the `From` trait, pattern matching, and iterator methods `flat_map()` and `partition()`.

Also explained in

Compare how 8 books explain result type →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Idiomatic Rust. The section links point to the parts of the book it draws on.