rust - 比赛背后的魔力:没有对`&std::option::Option <ListNode>的实现== std::option::Option <_>

标签 rust match ownership

我是Python中Rust的新手。这是我学习Rust的第四天。
在第一个问题Type casting for Option type之后,我有一个跟语法match和所有权概念有关的后续问题。

首先,我声明一个带有ListNode实现的new结构。

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ListNode {
  pub val: i32,
}

impl ListNode {
  #[inline]
  fn new(val: i32) -> Self {
    ListNode {
      val
    }
  }
}
我的目标是通过比较节点的val来比较两个节点是否相同。这是我的丑陋实现。
fn is_same(a: &Option<ListNode>, b: &Option<ListNode>) -> bool {
    if a == None && b == None { return true; }
    else if a == None && b != None { return false; }
    else if a != None && b == None { return false; }

    let ca: ListNode = a.clone().unwrap_or(ListNode::new(0));
    let cb: ListNode = b.clone().unwrap_or(ListNode::new(0));
    if ca.val == cb.val { return true; }
    else { return false; }
}

fn main() {
    let a: Option<ListNode> = Some(ListNode::new(0));
    let b: Option<ListNode> = Some(ListNode::new(0));
    
    println!("{:?}", is_same(&a, &b));
}
然后,我有很多错误...
no implementation for `&std::option::Option<ListNode> == std::option::Option<_>
根据我对所有权概念的了解,将*用作借入参数应该是可选的。但是,要进行比较,我需要添加*。下面的修改功能起作用。 (另一个发现是,使用a.clone()很好,但是*a.clone()错误,错误是type `ListNode` cannot be dereferenced。)
fn is_same(a: &Option<ListNode>, b: &Option<ListNode>) -> bool {
    if *a == None && *b == None { return true; }
    else if *a == None && *b != None { return false; }
    else if *a != None && *b == None { return false; }

    let ca: ListNode = a.clone().unwrap_or(ListNode::new(0));
    let cb: ListNode = b.clone().unwrap_or(ListNode::new(0));
    if ca.val == cb.val { return true; }
    else { return false; }
}
由于上述解决方案代码太丑陋,因此这是另一种使用match的实现,而没有多余的unwrap_or*
fn is_same(a: &Option<ListNode>, b: &Option<ListNode>) -> bool {
    match (a, b) {
        (None, None) => true,
        (None, _) => false,
        (_, None) => false,
        (Some(a), Some(b)) => a.val == b.val,
    }
}
这完美地工作了,ab与没有None*unwrap_or成功地进行了比较。

这些代码结束于以下问题:
  • 为什么在我的原始代码中需要*与None进行比较?
  • match背后的魔力是什么?这种语法如何使代码跳过(使用*unwrap_or进行比较)?
  • 最佳答案

    Why * is needed to compare with None in my original code?


    本身并不需要,但是Eq仅针对相同类型实现,因此您需要比较两个Option<T>或两个&Option<T>。从中您可能会看到comparing your nodes to &None would also have worked

    What is the magic behind match? How does this syntax make code skip using * and unwrap_or for comparison?


    Match Ergonomics。基本上,match将尝试自动添加对模式的引用,以尝试解析类型。
    另外我不知道您是否注意到了,只是想更加努力地工作,但是Option<T: Eq>实现了Eq,所以is_same(&a, &b) could just be written a == b
    另外,通常建议不要使用#[inline],通常最好避免提供提示,除非您专门查看了生成的输出并且编译器拒绝提供您正在寻找的内容。请记住:这里的代码是如此简单,以至于在发行模式下,甚至使用复杂的is_same版本进行大量取消引用后,llvm都会发现什么,然后加载并格式化一个恒定的true

    关于rust - 比赛背后的魔力:没有对`&std::option::Option <ListNode>的实现== std::option::Option <_>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62875622/

    相关文章:

    德尔福所有权困惑

    rust - 在 Rust 中使用引用和使用拥有的值有区别吗?

    rust - 如何在不丢弃物体的情况下解构物体?

    mysql - 如何验证数据源名称是否有效?

    rust - 如何将一片特征对象传递给C

    JavaScript 找到单词最多的句子

    excel - excel中的部分匹配,匹配条件中的多个值以匹配列表

    rust - 方法 `draw`存在,但在Vec <Box <dyn Trait >>中不满足以下特征范围,Compilernote应该满足吗? [复制]

    rust - Rust:在 “poll”中找不到 `impl std::future::Future`方法

    regex - Go : strings or regexp 中短字符串前缀匹配的更好方法