Skip to content

Instantly share code, notes, and snippets.

@cgwalters
Last active June 28, 2022 18:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cgwalters/fd91b211a78ae5ca6a0a1081a0f2821a to your computer and use it in GitHub Desktop.
Save cgwalters/fd91b211a78ae5ca6a0a1081a0f2821a to your computer and use it in GitHub Desktop.
Option and Result idioms

In Rust, the Option and Result types are really common. Here are a few idioms I've discovered for working with them using combinators which can simplify code:

map(Ok).unwrap_or_else(): Taking Option with fallible fallback to T

    // Our program needs a string for something (e.g. filename, database table name, etc).
    // To start, we can get this as an optional string - here a CLI argument, but it could be anything; e.g.
    // a value parsed from JSON, etc.  The `.nth(1)` call here gives us an `Option<String>`.
    // We want to compute a fallback value, but doing so can fail (e.g. return `Result<String>`).
    // Here's the trick - we use `.map(Ok)` to convert our `Option<String>` to `Option<Result<String>>`,
    // which means the type signature works for `.unwrap_or_else()`, giving us in the end a Result<String>,
    // on which we can use the regular `?` operator.
    let v: String = std::env::args()
        .nth(1)
        .map(Ok)
        .unwrap_or_else(|| std::fs::read_to_string("/etc/someconfig.conf"))?;

transpose: Fallible Option processing (map + Result) -> Option

    // We start with an optional string (but this could be any Option<T>).
    // We want to perform a falliable operation on it, giving us an Option<Result<T>>;
    // here T is u64 - we're just parsing the string.  But, this could e.g. be loading
    // the file contents with that name, looking up a value in a database, etc.
    // The `transpose()` method swaps that to `Result<Option<T>>
    // on which we can use the regular `?` operator, ending up with our mapped/processed value.
    let v: Option<u64> = std::env::args()
        .nth(1)
        .map(|o| o.parse::<u64>())
        .transpose()?;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment