HiveBrain v1.2.0
Get Started
← Back to all entries
patternrustMajor

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

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
assert_eqimplementedwhyusingrustmatch

Problem

Here's Rust's assert_eq! macro implementation. I've copied only the first branch for brevity:

macro_rules! assert_eq {
    ($left:expr, $right:expr) => ({
        match (&$left, &$right) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    panic!(r#"assertion failed: `(left == right)`
  left: `{:?}`,
 right: `{:?}`"#, left_val, right_val)
                }
            }
        }
    });
}


What's the purpose of the match here? Why isn't checking for non-equality enough?

Solution

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.

Code Snippets

macro_rules! assert_eq_2 {
        ($left:expr, $right:expr) => ({
            if !($left == $right) {
                panic!(r#"assertion failed: `(left == right)`
  left: `{:?}`,
 right: `{:?}`"#, $left, $right)
            }
        });
    }
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);
{
    if !(really_complex_fn() == 1) {
        panic!(r#"assertion failed: `(left == right)`
  left: `{:?}`,
 right: `{:?}`"#, really_complex_fn(), 1)
    }
}

Context

Stack Overflow Q#48732263, score: 68

Revisions (0)

No revisions yet.