在Rust中借用并返回可变引用的优雅方式

时间:2016-06-29 21:32:00

标签: reference rust mutable borrowing

我正在尝试对其执行某些操作后返回一个可变引用。最好用一段代码来解释:

#[derive(PartialEq)]
pub enum Value {
    Null,
    Array(Vec<Value>),
}

impl Value {
    pub fn new() -> Value {
        Value::Array(Vec::new())
    }

    pub fn push<'a, T> (&'a mut self, value: T) -> Option<&'a mut Value>
    where T:Into<Value> {
        let temp = match *self {
            Value::Array(ref mut vec) => {
                vec.push(value.into());
                true
            },
            _ => false,
        };
        if temp {
            Some(self)
        } else {
            None
        }
    }
}

#[test]
fn push_test() {
    let mut val = Value::new();
    val.push(Value::Null);
    assert!(val == Value::Array(vec![Value::Null]));
}

播放版本为here。布尔值的解决方法是因为如果我从Some(self)块中返回match,我将多次借用。有没有一种优雅的方法来实现push函数而不使用布尔值?如果它可以保留功能签名那么它的奖金。谢谢!

1 个答案:

答案 0 :(得分:1)

  

使用布尔值的解决方法是因为如果我从匹配块中返回Some(self),我会多次借用

另一种选择是暂时替换self,因此v可以获取向量的所有权(避免借用)。将新项目添加到v后,我们会重新构建self值:

// the lifetime 'a can be omitted
pub fn push<T>(&mut self, value: T) -> Option<&mut Value>
    where T: Into<Value>
{
    // replace put Value::Null on self and return the old value
    match ::std::mem::replace(self, Value::Null) {
        Value::Array(mut v) => {
            v.push(value.into());
            *self = Value::Array(v);
            Some(self)
        },
        _ => None,
    }
}