2016-06-29 45 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。布爾值的解決方法是因爲如果我從match塊中返回Some(self),我將多次借用。有沒有一種優雅的方式來實現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, 
    } 
}