具有可变引用的临时元组的模式匹配

Pattern matching on a temporary tuple with mutable references

我是 Rust 的新手,想知道是否有一种自然的方式来编写以下内容,同时仍在元组上进行模式匹配。

我有一个树状结构,有 keyvalueleftright 成员。我想创建一个类似于

的插入函数
fn insert(&mut self, k: K, v: V) -> Option<V> {
    match (k.cmp(self.k.borrow()), &mut self.left, &mut self.right) {
        (Ordering::Less, &mut None, _) => { self.left = Some(Box::new(TreeNode::new(k, v))); None },
        (Ordering::Less, &mut Some(ref mut left), _) => left.insert(k, v),
        (Ordering::Greater, &mut None, _) => { self.right = Some(Box::new(TreeNode::new(k, v))); None },
        (Ordering::Greater, &mut Some(ref mut right), _) => right.insert(k, v),
        (Ordering::Equal, _, _) => { let mut temp = v; std::mem::swap(self.v.borrow_mut(), temp.borrow_mut()); Some(temp) },
    }
}

我喜欢这清楚地涵盖了所有情况和结果操作,但是这不会编译,因为 self.leftself.right 被 match 语句中使用的临时元组可变地借用了意思我无法在比赛的动作臂内修改 self.leftself.right。以下替代作品

fn insert(&mut self, k: K, v: V) -> Option<V> {
    match k.cmp(self.k.borrow()) {
        Ordering::Less => match self.left {
            None => { self.left = Some(Box::new(TreeNode::new(k, v))); None },
            Some(ref mut left) => left.insert(k, v),
        },
        Ordering::Greater => match self.right {
            None => { self.right = Some(Box::new(TreeNode::new(k, v))); None },
            Some(ref mut right) => right.insert(k, v),
        },
        Ordering::Equal => { let mut temp = v; std::mem::swap(self.v.borrow_mut(), temp.borrow_mut()); Some(temp) }
    }
}

和逻辑上应该是等价的,但我感觉前者更清楚简洁地描述了问题。作为 Rust 的新手,我不确定是否有某种能力从元组中提取可变引用并在操作中将其从 None 更改为 Some 值,所以我想我会问是否有有没有我忽略的替代方案。

我已将 working and non-working 变体的简短片段上传到围栏。

有一种获取可变引用的方法,因为可以使用 @ 模式(在 Haskell 中称为 as 模式)将标识符绑定到整个值图案代表:

fn insert(&mut self, k: K, v: V) -> Option<V> {
    match (k.cmp(self.k.borrow()), &mut self.left, &mut self.right) {
        (Ordering::Less, left @ &mut None, _) => {
            *left = Some(Box::new(TreeNode::new(k, v)));
            None
        }
    // ...

这与在火柴臂内写 let left = &mut self.left; 完全一样,但它具有工作的有用优势。