我是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,
}
}
这完美地工作了,a
和b
与没有None
和*
的unwrap_or
成功地进行了比较。这些代码结束于以下问题:
*
与None进行比较? match
背后的魔力是什么?这种语法如何使代码跳过(使用*
和unwrap_or
进行比较)? 最佳答案
Why
*
is needed to compare withNone
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/