Rust: Write “?” Like A Boss

zhao chang
3 min readOct 1, 2021

Are you not a programmer?

Thanks for reading and Bye.

.

.

.

You have no idea what Rust is?

Thanks for reading and Bye.

.

.

.

You know Rust however you are NOT interested into writing question-marks like a boss?

Thanks for reading and Bye Bye.

.

.

.

— — — — — — — — — — —

Aite, thanks for passing above tests. Now you are one of my target audiences who knows Rust as a programming language. You may or may not be familiar with what Rust has to offer, such as zero-cost abstractions, memory safety via not GC, needs no runtime… But that’s ok, because those are not something we are gonna talk about today.

What we do talk about is a very specific topic: how to write “?” operators properly in Rust.

Talk is cheap, I’ll show you the code.

As a decent programmer, the first things bothers you hopefully are the yellow wavy lines. They are because the returned Result is being ignored.

we can make the compiler happy easily, by doing this:

BUT: nested “if”s looking ugly, let’s get rid of it.

It looks a little bit better doesn’t it? But we can make it even more concise:

or :

So “?”s save us a few lines of code in each of its usages.

You probably is wondering what is that horrible “Box<dyn Error+Sync+Send>”? This thing itself is worth another page. For now let’s just say it is my habit when Boxing errors in Rust, and we may or may not appreciate it in the context of multi-threading.

You probably already know that Rust provides 2 very import enums in its std library:

  1. Enum std::option::Option
  2. Enum std::result::Result

As my personal rule of thumb, all Rust functions shall return either one of the above 2.

We are extremely lucky if all functions in the invoking chain returns: Result<(), Box<dyn Error + Sync + Send>>, in which case we can write question-mark operator all the way like the example I shared above.

So what if a function returns NOT the same type of Result?

Result::map_err() to the rescue:

with this you can easily convert any Result to the type of Result being expected.

Aite, then what if a function returns Option ?

Again you can easily convert an Option to the type of expected Result.

in a lot of cases this is even better, because the closure will be evaluated only when there is need to return error.

I think you see what I mean. To sum up:

  1. Always wrap function that might fail somehow using Result
  2. Avoid nested-ifs, because it looks so ugly.
  3. Write “?” like a Boss!

--

--