2016-06-29 9 views
0

Я пытаюсь вернуть изменчивую ссылку после выполнения некоторой операции над ней. Это лучше всего объяснить кусок кода:Элегантный способ заимствовать и возвращать изменяемую ссылку в Rust

#[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

Обойти с булевыми значениями, потому что я был бы занимать несколько раз, если я вернусь 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, 
    } 
}