Result<Option<T>,E> vs. Result<T,F>

I have function that looks up a Thing given a name. There are three outcomes:

  • The name is invalid; this is an error.
  • The name is valid and the Thing is found. This is OK.
  • The name is valid and the Thing is not found. This also is OK.

It's only by doing the lookup that I can know whether the name is valid or invalid.

I have a standard error type I use in this code base; call it MyErr.

At present I return Result<Option<Thing>,MyErr>, which represents the three outcomes, two normal and one in error.

I could also return Result<Thing,MyNewErr> where MyNewErr could provide a way of distinguishing between "not found" and a genuine error.

And MyNewErr could simply be Option<MyErr>

I prefer what I'm doing now, because then I can propagate MyErr using ? in the normal way; but I'm wondering if there's a more idiomatic way to handle this pattern.

Both seems legit. I would decide which way to go basing on typical use case - how the "name is valid and thing is not found" would be handled in most ways? Would it be handled in one of branches of "ok" or "err" cases?

If it would be different branch in most cases, then there is additional question - would it be propagated up often? Or would this result benefit on easy maping the result? If yes, then I would go for just Result<T, F> because you can just .map the result. Also ? would not help with propagating the "valid but not found" case.

On the other hand - if you would often like to just filter up an error (for eg. with ?) and then operating on Option, then Result<Option<T>, E> would be much more handy.

If almost every case of usage of your function ends up beeing matched right after a call, then I would go with Result<Option<T>, E>, just to not create additional error type for every such case.

Result<Option> is the usual way to express this. Callers can still do:

lookup()?.ok_or(NotFoundErr)?

to reduce it to one error.

4 Likes

Usually if it's the invalid case I want to propagate it up immediately as a normal MyErr, just to clear the decks; then I'll address whether it was found our not.

OK, so even though Result<Option<T>, E> looks funny to me, it's idiomatic. Good enough.

Thanks, everybody!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.