brundolf
brundolf

Reputation: 1500

Deep Rust matching: is there a better way?

I just found myself writing this:

fn init_timestamps(dir: &PathBuf, file_timestamps: &'static HashMap<PathBuf,Duration>) {

    match fs::read_dir(dir) {
        Ok(iter) => iter.for_each(|result| match result {
            Ok(entry)  => {
                if entry.file_type().map(|t| t.is_dir()).unwrap_or(false) {
                    init_timestamps(&entry.path(), file_timestamps);
                } else {
                    match entry.metadata() {
                        Ok(md) => match md.modified() {
                            Ok(modified) => {
                                locked_timestamps.insert(entry.path(), modified.duration_since(SystemTime::UNIX_EPOCH).unwrap());
                            },
                            Err(_) => ()
                        },
                        Err(_) => ()
                    };
                }
            },
            Err(_) => ()
        }),
        Err(_) => ()
    };
}

And I have to ask: is there a better pattern I'm missing? I tried using .map() at each level, which looked slightly better but gave me compiler warnings about unused Results. What I'm wanting to do, in this general case, is "if this chain of Results (or Options) exists all the way down, do X. otherwise, do nothing." I've also run into similar situations where I want to coerce "failed" points in the chain to false (there's a boolean check at the fullest depth).

This actually could be seen as Rust's version of the null-check problem addressed with the null-coalescing operator in other languages such as Kotlin.

Upvotes: 2

Views: 924

Answers (1)

Silvio Mayolo
Silvio Mayolo

Reputation: 70297

You're looking for the ? operator, designed for this exact task.

foo()?

is equivalent to

match foo() {
    Ok(t)  => t
    Err(e) => return Err(e.into()),
}

So you can just throw ? at the end of anything that returns a Try implementation. You'll have to make your function return Result<(), E>, but that's just as well because then your function will report its errors rather than failing silently.

Upvotes: 5

Related Questions