Здесь Rust assert_eq!
макро-реализация. Для краткости я скопировал только первую ветку:
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)
}
}
}
});
}
Какова цель match
здесь? Почему не проверяется недостаточно для равенства?
Ответ 1
Хорошо, позвольте удалить матч.
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)
}
}
Как вы можете видеть, мы вызываем функцию дважды. Это меньше, чем идеально, тем более, если результат функции может меняться каждый раз, когда он называется.
match
- это просто быстрый и простой способ оценить оба аргумента макроса ровно один раз и привязать их к именам переменных.