在具有可变引用的临时元组上进行模式匹配

ggr*_*iii 2 rust

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

我有一个树状结构key,value,leftright成员.我想创建一个看起来类似的插入函数

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) },
    }
}
Run Code Online (Sandbox Code Playgroud)

我喜欢这清楚地涵盖了所有的情况和结果的行为,但是这不会编译因为self.left并且self.right可以被匹配语句中使用的临时元组可变地借用,这意味着我无法修改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) }
    }
}
Run Code Online (Sandbox Code Playgroud)

并且应该在逻辑上等同,但我觉得前者更清楚,更简洁地描述了问题.作为新生锈我不知道是否有提取从元组中的可变引用,并从改变一些能力None,以Some在操作价值,所以想我会问,如果有我俯瞰任何替代品.

我已经将工作非工作变体的简短片段上传到了围栏.

huo*_*uon 6

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

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
        }
    // ...
Run Code Online (Sandbox Code Playgroud)

这就像let left = &mut self.left;在匹配臂内写字一样,但它具有工作的有用优势.