rust - 元组如何被解构为引用?
问题描述
我正在看这个Condvar
例子,很好奇元组pair
和pair2
被解构的方式:
let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair2 = pair.clone();
// ...
thread::spawn(move|| {
let &(ref lock, ref cvar) = &*pair2;
// ...
}
删除&
from pair2
:
let &(ref lock, ref cvar) = *pair2;
正如我预期的那样给出编译器错误:
11 | let &(ref lock, ref cvar) = *pair2;
| ^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
|
= note: expected type `(std::sync::Mutex<bool>, std::sync::Condvar)`
found type `&_`
&
但是,如果删除元组周围的,它似乎编译和运行良好:
let (ref lock, ref cvar) = &*pair2;
或者如果两个&
' 都被删除:
let (ref lock, ref cvar) = *pair2;
甚至与
let (lock, cvar) = &*pair2;
编译器是否在后一种情况下帮助我们?
解决方案
编译器正在帮助我们使用匹配人体工程学。匹配人体工程学适用于元组解构和match
表达式;我们将首先查看match
表达式的大小写。
当引用匹配到非引用模式时,匹配人体工程学简化了 Rust 绑定变量的方式:
let x = Some(42);
let x_ref = &x;
match x_ref { // <-- reference match expression: `x_ref`
Some(a) => {}, // <-- non-reference pattern: `Some(a)`
None => {},
}
旧版本的 Rust 编译器不允许这样做。相反,必须在模式中指定引用 ( &
):
// Old Rust
match x_ref {
&Some(a) => {},
&None => {},
}
或在匹配之前取消引用:
// Old Rust
match *x_ref {
Some(a) => {},
None => {},
}
请注意,a
拥有Option
的内部值,这对于非Copy
类型是有问题的。为了避免这种情况,还不得不借用内在价值。这是通过使用关键字绑定a
为引用来完成的:ref
// Old Rust
let x = Some(Box::new(42));
let x_ref = &x;
match x_ref {
&Some(ref a) => {},
&None => {},
}
或者
// Old Rust
match *x_ref {
Some(ref a) => {},
None => {},
}
Rust 的新匹配人体工程学允许简化版本:
// New Rust
match x_ref {
Some(a) => {
// x_ref is automatically dereferenced
// a is automatically bound as a reference
},
None => {},
}
对于两者Copy
和非Copy
类型。
将此应用于元组解构,
let pair = Arc::new((Mutex::new(false), Condvar::new()));
let (lock, cvar) = &*pair;
// ^^^^^^ reference match expression
// ^^^^^^^^^^^^ non-reference pattern
*pair
是一个元组&*pair
是对元组的引用- 两者都
lock
被cvar
绑定为引用
另请参阅以下 Stack Overflow 帖子:
推荐阅读
- javascript - 有没有办法使用纯 javascript 或 jquery 来缩短 url?
- flutter - 从 Flutter 中的 SecondScreen 调用 FirstScreen 的设置状态
- python - 理解“backward()”:如何从头开始编写 Pytorch 函数“.backward()”?
- android - 为什么 apk 仅在 Android 10 的发布版本中中止?
- javascript - 如何将数据从 Angular 应用程序组件发送到 index.js(节点服务器)
- android - 如何在调用 getItemCount() 之前在 RecyclerView Adapter 的构造函数中从 Firebase Firestore 加载数据?
- python - 如何在存储库级别禁用 PyCharm 中的特定 PEP8 警告?
- assembly - lahf 什么时候可以在 x86-64 模式下使用?
- docker - Docker pull hello-world 显示创建成功,但使用 docker ps 或 docker ps -a 时没有显示图像
- reactjs - 为什么我的状态钩子没有正确更新?