当两个选项包含可以测试相等的值时,测试两个选项是否相同的最惯用的方法是什么?

She*_*ter 9 rust

我有两种类型可以测试相等性.但是,一旦我将它们包装在Options中,各种PartialEq实现提供的精确性就会出现在窗外.我必须使用map或以其他方式转换它们.

举个例子,让我们使用&strString:

fn main() {
    let a = "hello";
    let b = "hello".to_owned();

    assert_eq!(a, b); // Just fine

    let a = Some(a);
    let b = Some(b);

    // error: mismatched types
    assert_eq!(a, b);

    // error: mismatched types
    assert_eq!(a, b.as_ref());

    // works, but highly tied to strings or slices,
    // requires me to remember which is which
    assert_eq!(a, b.as_ref().map(|x| &x[..]));
}
Run Code Online (Sandbox Code Playgroud)

肯定必须有一个更简单或更直接的方法来做到这一点?

侧面问题 - 是什么阻碍了更广泛的Option实施PartialEq?我猜是连贯性,我的老对手.

impl<T, U> PartialEq<Option<U>> for Option<T>
where
    T: PartialEq<U>,
Run Code Online (Sandbox Code Playgroud)

有一个关于这在一些喋喋不休的RFC和锈的问题(1,2).

Sta*_*eur 7

从 Rust 1.40 开始,您可以使用,as_deref()这样您就不必记住什么是什么:

assert_eq!(a.as_deref(), b.as_deref());
Run Code Online (Sandbox Code Playgroud)

在 Rust 1.40 之前,我会做这样的事情:

match (&a, &b) {
    (Some(a), Some(b)) => assert_eq!(a, b),
    (None, None) => (),
    _ => panic!("a and b not equal"),
}
Run Code Online (Sandbox Code Playgroud)

另一种选择是自定义断言,基于assert_eq!

macro_rules! cmp_eq_option {
    ($left:expr, $right:expr) => {{
        match (&$left, &$right) {
            (Some(left_val), Some(right_val)) => *left_val == *right_val,
            (None, None) => true,
            _ => false,
        }
    }};
}

#[macro_export]
macro_rules! assert_eq_option {
    ($left:expr, $right:expr) => ({
        if !cmp_eq_option!($left, $right) {
            panic!(r#"assertion failed: `(left == right)`
  left: `{:?}`,
 right: `{:?}`"#, $left, $right)
        }
    });
    ($left:expr, $right:expr,) => ({
        assert_eq_option!($left, $right)
    });
    ($left:expr, $right:expr, $($arg:tt)+) => ({
        if !cmp_eq_option!($left, $right) {
            panic!(r#"assertion failed: `(left == right)`
  left: `{:?}`,
 right: `{:?}`: {}"#, $left, $right, format_args!($($arg)+))
        }
    });
}
Run Code Online (Sandbox Code Playgroud)