1

I'm trying to return a mutable reference after doing some operation on it. This is best explained by a piece of code:

#[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]));
}

The play version is here. The workaround with boolean values is because I would be borrowing multiple times if I return Some(self) from within the match block. Is there an elegant way to implement the push function without using boolean values? If its possible to retain the function signature then its a bonus. Thank you!

1 Answer 1

1

The workaround with boolean values is because I would be borrowing multiple times if I return Some(self) from within the match block

Another option is to replace self temporally, so v can take the ownership of the vector (avoiding the borrow). After adding the new item to v, we reconstruct the self value:

// 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,
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.