4

Rust コミュニティの寛大な支援により、マネージ ポインターを使用して組み立てられたトポロジ データ構造のベースを取得することができました。これはかなりうまくまとまり、私は一般的に Rust についてかなり興奮していました。次に、この投稿を読みました(これは合理的な計画のように思えます)。これをきっかけに、可能であれば、所有されているポインターのみを使用して、後戻りして再構築しようとしました。

これは、マネージ ポインターを使用した作業バージョンです。

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);
}   }   }   }   }   }    

ライフタイムエラーを数時間追跡した後、周期的な性質のために、所有されているポインターではこれが不可能である可能性があるという結論に達しました (警告されたように結び目を結ぶことなく)。これに対する私の弱い試みは以下のとおりです。私の質問は、マネージ ポインターに頼らずにこの構造を実装することは可能ですか? そうでない場合、上記のコードは合理的に「錆びている」と見なされますか? (慣用的な錆)。ありがとう。

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);              
    }
} 
4

1 に答える 1

2

&mut一度に存在できるポインタは 1 つだけなので、ポインタの使用は不可能であると確信しています。

fn main() {
    let mut i = 0;
    let a = &mut i;
    let b = &mut i;
}
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安全でないポインタをメモリ ( ) に格納するか、インデックスを のdartsメンバーに格納することで、安全でない借用チェッカーを回避できますGMap。基本的に、メモリへの単一の参照を格納し(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型を取る必要があります。

(まったく別の話ですが、外部 iteratorsのライブラリ サポートがあります。これは、内部 iterators (クロージャーを取るもの) よりもはるかに構成可能です。したがって、これらのいずれtraverseかを for に定義すると、それをより適切に使用できる場合とそうでない場合があります。 )

于 2013-06-04T08:50:36.753 に答える