元组如何被分解为参考? [英] How are Tuples destructured into references?
问题描述
我正在查看 Condvar
示例,并很好奇元组 pair
和 pair2
的结构如何:
I'm looking at the Condvar
example and am curious how the tuples pair
and pair2
are destructured:
let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair2 = pair.clone();
// ...
thread::spawn(move|| {
let &(ref lock, ref cvar) = &*pair2;
// ...
}
从 pair2
中删除&
:
let &(ref lock, ref cvar) = *pair2;
产生了我期望的编译器错误:
gives a compiler error as I expected:
11 | let &(ref lock, ref cvar) = *pair2;
| ^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
|
= note: expected type `(std::sync::Mutex<bool>, std::sync::Condvar)`
found type `&_`
但是,如果删除元组周围的&
,它似乎可以编译并运行良好:
However, it seems to compile and run fine if the &
around the tuple is removed:
let (ref lock, ref cvar) = &*pair2;
,或者两个&
都被删除了:
or if both of the &
's are removed:
let (ref lock, ref cvar) = *pair2;
或什至
let (lock, cvar) = &*pair2;
在后一种情况下,编译器是否在帮助我们?
Is the compiler is helping us in the latter cases?
推荐答案
编译器正在帮助我们使用匹配人体工程学.匹配人体工程学适用于元组分解和 match
表达式;我们将首先查看 match
表达式的情况.
The compiler is helping us using match ergonomics. Match ergonomics applies to tuple destructuring and the match
expression; we'll look at the case of the match
expression first.
匹配人体工程学简化了引用与非引用模式匹配时Rust绑定变量的方式:
Match ergonomics simplifies how Rust binds variables when a reference is matched to a non-reference pattern:
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编译器不允许这样做.相反,必须在模式中指定引用(&
):
Older version of the Rust compiler didn't allow this. Instead, one had to either specify references (&
) in the pattern:
// Old Rust
match x_ref {
&Some(a) => {},
&None => {},
}
或在匹配前取消引用:
// Old Rust
match *x_ref {
Some(a) => {},
None => {},
}
请注意, a
拥有 Option
的内部值,这对于非 Copy
类型来说是有问题的.为了避免这种情况,还必须借用内在价值.这是通过使用 ref
关键字将 a
绑定为参考来完成的:
Notice that a
owns the Option
's inner value, which is problematic for non-Copy
types. To avoid this, one also had to borrow the inner value. This is done by binding a
as a reference using the ref
keyword:
// 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的新匹配人体工程学允许使用简化版本:
Rust's new match ergonomics allow a simplified version:
// 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
均被绑定为引用 *pair
is a tuple&*pair
is a reference to a tuple- Both
lock
andcvar
are bound as references
另请参阅以下这些Stack Overflow帖子:
Also see these Stack Overflow posts on:
这篇关于元组如何被分解为参考?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!