匹配背后的魔法:`&std::option::Option<ListNode> == std::option::Option<_> 没有实现
Magic behind match: no implementation for `&std::option::Option<ListNode> == std::option::Option<_>
我是 Python 的 Rust 新手。这是我学习 Rust 的第 4 天。
在我的第一个问题 之后,我有一个与语法 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
与没有 *
和 unwrap_or
的 None
成功比较。
这些代码结束于以下问题:
- 为什么我的原始代码中需要
*
来与 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
。
我是 Python 的 Rust 新手。这是我学习 Rust 的第 4 天。
在我的第一个问题 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
与没有 *
和 unwrap_or
的 None
成功比较。
这些代码结束于以下问题:
- 为什么我的原始代码中需要
*
来与 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
。