Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 为什么在元组模式匹配中需要显式借用?_Rust_Pattern Matching_Move Semantics - Fatal编程技术网

Rust 为什么在元组模式匹配中需要显式借用?

Rust 为什么在元组模式匹配中需要显式借用?,rust,pattern-matching,move-semantics,Rust,Pattern Matching,Move Semantics,我正在用Rust写一棵二叉树,借阅检查器真的把我弄糊涂了。这是 二叉树的定义如下: struct NonEmptyNode; pub struct BinaryTree { root: Option<NonEmptyNode>, } 错误消息是 错误[E0507]:无法移出借用的内容 -->src/main.rs:10:16 | 10 |匹配(self.root、bt.root){ |^^^^无法移出借用的内容 错误[E0507]:无法移出借用的内容 -->src/mai

我正在用Rust写一棵二叉树,借阅检查器真的把我弄糊涂了。这是

二叉树的定义如下:

struct NonEmptyNode;

pub struct BinaryTree {
    root: Option<NonEmptyNode>,
}
错误消息是

错误[E0507]:无法移出借用的内容
-->src/main.rs:10:16
|
10 |匹配(self.root、bt.root){
|^^^^无法移出借用的内容
错误[E0507]:无法移出借用的内容
-->src/main.rs:10:27
|
10 |匹配(self.root、bt.root){
|^^无法移出借用的内容
要使其工作,必须将代码修改为:

// Implementation #2
fn set_child_helper(&self, bt: &Self, setter: fn(&NonEmptyNode, &NonEmptyNode)) -> bool {
    match (&self.root, &bt.root) {
        // explicit borrow
        (&Some(ref rt), &Some(ref node)) => {
            // explicit borrow
            setter(rt, node);
            true
        }
        _ => false,
    }
}
如果在没有显式借用的情况下,我一次匹配一个变量,借用检查器根本不会抱怨:

// Implementation #3
fn set_child_helper(&self, bt: &Self, setter: fn(&NonEmptyNode, &NonEmptyNode)) -> bool {
    match self.root {
        Some(ref rt) => match bt.root {
            // No explict borrow will be fine
            Some(ref node) => {
                // No explicit borrow will be fine
                setter(rt, node);
                true
            }
            _ => false,
        },
        _ => false,
    }
}

为什么实现#3不需要显式借用,而实现#1需要显式借用?

关键在于
self.root
bt.root
是s,而元组不是。之所以#3有效,是因为编译器知道如何“通过”中间表达式来绑定到原始存储位置

从另一个角度来看:非常简单的表达式,如
self.root
,其特殊之处在于它们的外观和行为类似于值(并且具有值类型),但编译器会秘密地记住它是如何达到该值的,允许它返回并获取指向该值读取位置的指针

判断某物是否为“位置表达式”的简单方法是尝试为其赋值。如果可以执行
expr=some_value;
,则
expr
必须为“位置表达式”。顺便说一句,这也是为什么在编写
&self.root
时,会得到指向存储
self.root
的位置的指针,而不是指向
self.root
副本的指针

这个“地方表达”业务不适用于元组,因为元组没有此属性。要构造元组,编译器必须实际读取元组元素的值,并将其移动或复制到元组的新存储中。这会破坏编译器可能具有的任何位置关联:这些值不再是以前的位置


最后,您可能想看看
选项::as_ref
,它将
&Option
转换为
选项
。这将允许您匹配
(self.root.as_ref()、bt.root.as_ref())
,模式类似于
(一些(rt),一些(node))
,这可能更方便。

关键是
self.root
bt.root
是s,而元组不是。之所以#3有效,是因为编译器知道如何“遍历”中间表达式以绑定到原始存储位置

从另一个角度来看:非常简单的表达式,如
self.root
,其特殊之处在于它们的外观和行为类似于值(并且具有值类型),但编译器会秘密地记住它是如何达到该值的,允许它返回并获取指向该值读取位置的指针

判断某物是否为“位置表达式”的简单方法是尝试为其赋值。如果可以执行
expr=some_value;
,则
expr
必须为“位置表达式”。顺便说一句,这也是为什么在编写
&self.root
时,会得到指向存储
self.root
的位置的指针,而不是指向
self.root
副本的指针

这个“地方表达”业务不适用于元组,因为元组没有此属性。要构造元组,编译器必须实际读取元组元素的值,并将其移动或复制到元组的新存储中。这会破坏编译器可能具有的任何位置关联:这些值不再是以前的位置

最后,您可能想看看
选项::as_ref
,它将
&Option
转换为
选项
。这将允许您匹配
(self.root.as_ref()、bt.root.as_ref())
,模式类似于
(一些(rt),一些(node))
,这可能更方便。

巧合的是,在你发布这个问题几个小时后,发布了这个问题,其中包括(除其他酷的事情外)自动引用和取消引用
匹配
模式的语义。这意味着当匹配
(&self.root,&bt.root)
时,你可以编写
(一些(rt),一些(node))
,编译器将智能地将
rt
node
转换为引用。()巧合的是,在你发布这个问题几小时后,发布了这个问题,其中包括(除其他酷的东西外)
匹配
模式的自动引用和取消引用语义。这意味着当匹配
(&self.root,&bt.root)
时,您可以编写
(一些(rt),一些(节点))
,编译器将智能地将
rt
节点
转换为引用。()
// Implementation #3
fn set_child_helper(&self, bt: &Self, setter: fn(&NonEmptyNode, &NonEmptyNode)) -> bool {
    match self.root {
        Some(ref rt) => match bt.root {
            // No explict borrow will be fine
            Some(ref node) => {
                // No explicit borrow will be fine
                setter(rt, node);
                true
            }
            _ => false,
        },
        _ => false,
    }
}