是否有可能同时进行可变绑定和解构?

Is it possible to have mutable binding and destructuring simultaneously?

提问人:Nawaz 提问时间:7/25/2022 最后编辑:Nawaz 更新时间:7/25/2022 访问量:163

问:

下面的代码按预期工作(演示),但这需要两个嵌套,我只想用一个替换。match {}

#![allow(unused)]
use std::collections::hash_map::HashMap;

#[derive(Debug, Clone)]
struct NormalTransaction(f64);

//  only normal transaction can be disputed.. BY DESIGN
#[derive(Debug, Clone)]
struct DisputeTransaction(NormalTransaction);

#[derive(Debug, Clone)]
enum Transaction {
    Normal(NormalTransaction),
    Dispute(DisputeTransaction),
}

fn main() {
    let mut m = HashMap::new();
    m.insert(1, Transaction::Normal(NormalTransaction(100.0)));
    
    println!("before: {:#?}", m);
    
    match m.get_mut(&1) {
        Some(t) => match t {
            Transaction::Normal(normal) => {
                *t = Transaction::Dispute(DisputeTransaction(normal.clone()));
            }   
            _ => {}, // NA
        }
        _ => {}, // NA
    }
    
    println!("after: {:#?}", m);
}

仅将两者替换为一个,如下所示:match{}

    match m.get_mut(&1) {
        Some(t @ Transaction::Normal(normal)) => {
            *t = Transaction::Dispute(DisputeTransaction(normal.clone()));
        }
        _ => {}, // NA
    }

但它不起作用,说(演示):

error: borrow of moved value
  --> src/main.rs:24:14
   |
24 |         Some(t @ Transaction::Normal(normal)) => {
   |              -^^^^^^^^^^^^^^^^^^^^^^^------^
   |              |                       |
   |              |                       value borrowed here after move
   |              value moved into `t` here
   |              move occurs because `t` has type `&mut Transaction` which does not implement the `Copy` trait

error[E0382]: borrow of moved value
  --> src/main.rs:24:38
   |
24 |         Some(t @ Transaction::Normal(normal)) => {
   |              ------------------------^^^^^^-
   |              |                       |
   |              |                       value borrowed here after move
   |              value moved here
   |
   = note: move occurs because value has type `&mut Transaction`, which does not implement the `Copy` trait
help: borrow this field in the pattern to avoid moving the value
   |
24 |         Some(ref t @ Transaction::Normal(normal)) => {
   |              +++

是否可以在单个匹配情况下进行可变绑定和解构?

模式匹配 解构 可变 借用检查器

评论

0赞 Finomnis 7/25/2022
我猜答案是否定的,随着解构。至少这是我的第一印象,老实说,我以前不知道:D@@

答:

2赞 orlp 7/25/2022 #1

我不知道使用单个匹配项的方法,但如果您使用 s 而不是匹配项,它看起来并不那么糟糕:if let

if let Some(t) = m.get_mut(&1) {
    if let Transaction::Normal(normal) = t {
        *t = Transaction::Dispute(DisputeTransaction(normal.clone()));
    }   
}

一旦 let-chains 落地,我相信你也应该会写

if let Some(t) = m.get_mut(&1) && let Transaction::Normal(normal) = t {
    *t = Transaction::Dispute(DisputeTransaction(normal.clone()));
}

评论

0赞 Nawaz 7/25/2022
是的。这就是我在发布问题后所写的。这似乎更好,特别是因为我不关心两个匹配表达式中的情况。所以代码更少!else
0赞 Nawaz 7/25/2022
顺便说一句,你忘记了 let-chains 代码中的第二个吗?还是不需要?let
1赞 orlp 7/25/2022
@Nawaz我只是忘记了,修复了。
0赞 Nawaz 8/2/2022
在没有更好的答案的情况下,我现在接受这个答案!