首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >魔术背后的匹配:没有实现的`&std::option::Option<ListNode> == std::option::Option<_>

魔术背后的匹配:没有实现的`&std::option::Option<ListNode> == std::option::Option<_>
EN

Stack Overflow用户
提问于 2020-07-13 12:13:47
回答 1查看 127关注 0票数 2

我是Python的生手。这是我学习锈的第四天。

在我的第一个问题可选类型的铸造之后,我有一个关于语法match和所有权概念的后续问题。

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

代码语言:javascript
复制
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ListNode {
  pub val: i32,
}

impl ListNode {
  #[inline]
  fn new(val: i32) -> Self {
    ListNode {
      val
    }
  }
}

我的目标是通过比较节点的val来比较两个节点是否相同。这是我丑陋的实现。

代码语言:javascript
复制
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));
}

然后我犯了很多错误..。

代码语言:javascript
复制
no implementation for `&std::option::Option<ListNode> == std::option::Option<_>

根据我对所有权概念的了解,使用*作为借来的参数应该是可选的。但是,为了使比较有效,我需要添加*。下面的修改函数可以工作。(另一个发现是,使用a.clone()是可以的,但是*a.clone()的错误type `ListNode` cannot be dereferenced是错误的。)

代码语言:javascript
复制
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*

代码语言:javascript
复制
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成功地与没有*unwrap_orNone进行了比较。

这些代码的结尾是以下问题:

  • 为什么需要将*与原始代码中的任何一个进行比较?
  • match背后的魔力是什么?这种语法如何使代码跳过使用*unwrap_or进行比较?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-13 12:56:19

为什么需要将*与我的原始代码中的None进行比较?

它本身并不需要,但是Eq只是为相同的类型实现的,所以您需要比较两个Option<T>或两个&Option<T>。从这个你可以看到也会起作用

火柴背后的魔力是什么?这种语法如何使代码跳过使用*和unwrap_or进行比较?

匹配人机工程学。基本上,match将尝试自动添加对模式的引用,以便尝试和解析这些类型。

另外,我不知道您是否注意到并只想更努力地工作,但是Option<T: Eq>实现了Eq,所以is_same(&a, &b) a == b

还有一件事,#[inline]通常被反对,通常最好避免提供提示,除非您专门查看了生成的输出,而编译器拒绝提供您想要的结果。请记住:这里的代码是如此简单,以至于在发布模式下,甚至在使用复杂版本的is_same时,llvm会发现什么是什么,并且只是加载和格式化一个常量的true

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62875622

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档