首页 > 解决方案 > 元组如何被解构为引用?

问题描述

我正在看这个Condvar例子,很好奇元组pairpair2被解构的方式:

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;

编译器是否在后一种情况下帮助我们?

标签: rusttuplesdestructuring

解决方案


编译器正在帮助我们使用匹配人体工程学。匹配人体工程学适用于元组解构和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是对元组的引用
  • 两者都lockcvar绑定为引用

另请参阅以下 Stack Overflow 帖子:


推荐阅读