Why is Rust’s assert_eq! implemented using a match?

Alright, let’s remove the match.

    macro_rules! assert_eq_2 {
        ($left:expr, $right:expr) => ({
            if !($left == $right) {
                panic!(r#"assertion failed: `(left == right)`
  left: `{:?}`,
 right: `{:?}`"#, $left, $right)
            }
        });
    }

Now, let’s pick a completely random example…

fn really_complex_fn() -> i32 {
    // Hit the disk, send some network requests,
    // and mine some bitcoin, then...
    return 1;
}

assert_eq_2!(really_complex_fn(), 1);

This would expand to…

{
    if !(really_complex_fn() == 1) {
        panic!(r#"assertion failed: `(left == right)`
  left: `{:?}`,
 right: `{:?}`"#, really_complex_fn(), 1)
    }
}

As you can see, we’re calling the function twice. That’s less than ideal, even more so if the result of the function could change each time it’s called.

The match is just a quick, easy way to evaluate both “arguments” to the macro exactly once and bind them to variable names.

Leave a Comment