Things I Learned About Rust

Rust has been a daily part of my life for about 8 months now. I’ve had the distinct and somewhat surprising pleasure of getting to work with it professionally for Red Canary. It’s been a whole lot of fun.

Every so often, I learn something new about writing Rust. Most recently, that was over-use of match statements. In particular, my code base has a number of cases where I’m dealing with the Result<V, E> type. I need to decompose the Result<V, E> into its constituent Ok(v) and Err(e) variants in order to branch logic.

However, there are a number of places where I use a result type similar to: Result<(), SomeError>. This results in a bunch of code that looks like:

let foo: Result<(), SomeError> = something_that_returns_result();
match foo {
	Ok(_) => {},
	Err(e) => println!("My error: {}", e.description())

Initially, I didn’t think to hard about writing that. It was short enough and the intent was clear to me. After starting to use cargo clippy fastidiously on my code base, it kept pointing out ways to simplify the use of the inverse pattern above for the Option<T> type:

let foo: Option<String> = something_that_returns_option();
match foo {
	Some(v) => do_a_thing_with_string(v),
	None => {}

cargo clippy kindly informed me that I should be using the if let... syntax instead of match for brevity:

if let Some(foo) = something_that_returns_option() {

After fixing a few of the cargo clippy lint issues [above][1], I realized I could do the same thing with those functions I used which returned Result<(), SomeError>, just the inverse:

if let Err(e) = something_that_returns_result() {
	println!("My error: {}", e.description();

That’s clearer and simplifies the thinking in my opinion.

PS: Maybe I should look at adding the inverse pattern to cargo clippy as a feature addition to that lint rule.

Posted on: 2018-08-23
Tagged as: programming, howto