2013-06-04 51 views
4

在鐵鏽社區的慷慨幫助下,我設法使用託管指針組裝了拓撲數據結構的基礎。這很好地融合在一起,我對Rust的整體感到非常興奮。然後我讀了這個post(這看起來像是一個合理的計劃),它激勵我回溯並儘可能地僅使用擁有的指針重新組裝它。圖結構中擁有的指針

這是使用管理指針的工作版本:

struct Dart<T> { 
    alpha: ~[@mut Dart<T>], 
    embed: ~[@mut T], 
    tagged: bool 
} 

impl<T> Dart<T> { 
    pub fn new(dim: uint) -> @mut Dart<T> { 
     let mut dart = @mut Dart{alpha: ~[], embed: ~[], tagged: false};   
     dart.alpha = vec::from_elem(dim, dart);    
     return dart; 
    } 
    pub fn get_dim(&self) -> uint { 
     return self.alpha.len(); 
    } 
    pub fn traverse(@mut self, invs: &[uint], f: &fn(&Dart<T>)) { 
     let dim = self.get_dim(); 
     for invs.each |i| {if *i >= dim {return}}; //test bounds on invs vec 
     if invs.len() == 2 { 
      let spread:int = int::abs(invs[1] as int - invs[0] as int); 
      if spread == 1 { //simple loop 
       let mut dart = self; 
       let mut i = invs[0]; 
       while !dart.tagged { 
        dart.tagged = true; 
        f(dart); 
        dart = dart.alpha[i]; 
        if i == invs[0] {i = invs[1];} 
        else {i == invs[0];} 
      } }   
      // else if spread == 2 { // max 4 cells traversed 

      // } 
     } 
     else { 
      let mut stack = ~[self]; 
      self.tagged = true;  
      while !stack.is_empty() { 
       let mut dart = stack.pop(); 
       f(dart); 
       for invs.each |i| { 
        if !dart.alpha[*i].tagged { 
         dart.alpha[*i].tagged = true; 
         stack.push(dart); 
} } } } } }  

追逐一生的錯誤的幾個小時裏,我已經得出結論之後,這甚至可能不會有可能與擁有的指針,由於週期性特徵(無需打結,因爲我是warned)。我對此的微弱嘗試如下。我的問題是,這種結構可以實現而不訴諸託管指針?如果不是,上面的代碼是否被認爲是合理的「生鏽」? (慣性生鏽)。謝謝。

struct GMap<'self,T> { 
    dim: uint, 
    darts: ~[~Dart<'self,T>] 
} 

struct Dart<'self,T> { 
    alpha: ~[&'self mut Dart<'self, T>], 
    embed: ~[&'self mut T], 
    tagged: bool 
} 

impl<'self, T> GMap<'self, T> { 
    pub fn new_dart(&'self mut self) { 
     let mut dart = ~Dart{alpha: ~[], embed: ~[], tagged: false}; 
     let dartRef: &'self mut Dart<'self, T> = dart; 
     dartRef.alpha = vec::from_elem(self.dim, copy dartRef); 
     self.darts.push(dart);    
    } 
} 

回答

2

我敢肯定,使用&mut指針是不可能的,因爲一次只能有存在一個這樣的指針在時間,例如:

and-mut.rs:4:12: 4:18 error: cannot borrow `i` as mutable more than once at at a time 
and-mut.rs:4  let b = &mut i; 
         ^~~~~~ 
and-mut.rs:3:12: 3:18 note: second borrow of `i` as mutable occurs here 
and-mut.rs:3  let a = &mut i; 
         ^~~~~~ 
error: aborting due to previous error 

一個能拿通過將不安全的指針存儲到內存(ptr::to_mut_unsafe_ptr)或索引到GMapdarts成員中,可以不安全地在借用檢查器周圍。實質上,將一個引用存儲到內存中(在self.darts中)並且所有操作都必須經過它。

這可能看起來像:

impl<'self, T> GMap<'self, T> { 
    pub fn new_dart(&'self mut self) { 
     let ind = self.darts.len(); 
     self.darts.push(~Dart{alpha: vec::from_elem(self.dim, ind), embed: ~[], tagged: false}); 
    } 
} 

traverse需要改變要麼是方法上GMap(例如fn(&mut self, node_ind: uint, invs: &[uint], f: &fn(&Dart<T>))),或至少採取GMap類型。

(在一個完全不同的音符,存在一種用於external iterators庫的支持,其比內部迭代(即採取封閉的那些)更可組合。因此,限定其中一個爲traverse可以(或者可以不)使得它更好用。)

+0

似乎在這種情況下,託管指針版本(GC或RC)的開銷可能是值得的。如果我使用地圖或散列表來保持飛鏢直線,那麼無論如何都會有一些開銷。謝謝。 – MFlamer

+0

除非使用地圖和擁有的指針讓我能夠並行遍歷...還不確定。 – MFlamer