当两个选项包含可以测试相等的值时,测试两个选项是否相等的最惯用的方法是什么? [英] What's the most idiomatic way to test two Options for equality when they contain values which can be tested for equality?

查看:32
本文介绍了当两个选项包含可以测试相等的值时,测试两个选项是否相等的最惯用的方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两种可以测试相等性的类型.然而,一旦我将它们包装在 Option 中,各种 PartialEq 实现所提供的细节就消失了.我必须使用 map 或以其他方式转换它们.

I have two types that can be tested for equality. However, once I wrap them in Options, the nicety provided by various PartialEq implementations goes right out the window. I have to use map or otherwise convert them.

例如,让我们使用 &strString:

As an example, let's use &str and String:

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[..]));
}

肯定有一种更简单或更直接的方法来做到这一点吗?

There surely must be a simpler or more straight-forward way to do this?

附带问题——是什么阻止了 Option 更广泛地实现 PartialEq?我在猜测一致性,我的宿敌.

Side-question — what prevents Option from implementing PartialEq a bit more broadly? I'm guessing coherence, my old nemesis.

impl<T, U> PartialEq<Option<U>> for Option<T>
where
    T: PartialEq<U>,

RFC 和 Rust 问题(1, 2).

There's some chatter about this in the RFCs and Rust issues (1, 2).

推荐答案

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

As of Rust 1.40, you can use as_deref() so you don't have to remember what is what:

assert_eq!(a.as_deref(), b.as_deref());

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

Before Rust 1.40, I would do something like this:

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

<小时>

另一个选项是自定义断言,基于 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)+))
        }
    });
}

这篇关于当两个选项包含可以测试相等的值时,测试两个选项是否相等的最惯用的方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆