可变结构体字段

4
我知道可变字段在0.6版本中已经被移除。使用这段代码时,我遇到了以下错误:
C:\Users\mflamer\Dropbox\Rust\Tests\gmap.rs:23:8: 23:18 错误: 赋值给不可变字段 C:\Users\mflamer\Dropbox\Rust\Tests\gmap.rs:23 dart.alpha = vec::from_elem(self.n + 1, dart);
请问这里出了什么问题?谢谢。
pub struct GMap<T> {
        priv     n: uint,
        priv darts: ~[Dart<T>]
    }

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

impl<T> GMap<T> {
    pub fn new(dim: uint) -> GMap<T> {      
        let mut map: GMap<T> = GMap{n: dim, darts: ~[]};
        return map
    }
    pub fn new_dart(&self, ) -> @Dart<T> {
        let mut dart = @Dart{alpha: ~[], embed: ~[], tagged: false};        
        dart.alpha = vec::from_elem(self.n + 1, dart); 
        //dart.embed = vec::from_elem(self.n + 1, );
        return dart;
    }
    pub fn dim(&self) -> uint {
        self.n 
    }
}


//pub fn traverse(&self,[bool,..])


enum Cell {
    Null,
    Vertex,
    Edge,
    Face,
    Solid
}   

fn main() { 
    let topo: GMap<Cell> = GMap::new(3);    
}
1个回答

6
问题在于可变性如何通过所有权继承。为了使某个东西可变,它的所有者必须是可变的。除非有一个新的所有者,否则所有权会继承下去,并且@&被归类为所有者。因此,在这种情况下,您拥有dart拥有@Dart盒子,但不拥有盒子的内容,因此x上的mut并不意味着盒子的内容是可变的(实际上,它不能是可变的,因为否则它可能会在引用它的其他内容下发生更改)。
解决这个问题的方法要么是使盒子成为可变盒子,以便dart结构的所有者是可变的,即@mut Dart { .. }(这具有(小)运行时惩罚,并且如果在借用为不可变时被修改,则可能使程序失败),要么一次性构建它。前者是非最优的,后者似乎很难实现。然而,前者可能看起来像:
struct Dart<T> {
    alpha: ~[@mut Dart<T>],
    embed: ~[@T],
   tagged: bool
}

// ...

    pub fn new_dart(&self, ) -> @mut Dart<T> {
        let dart = @mut Dart{alpha: ~[], embed: ~[], tagged: false};        
        dart.alpha = vec::from_elem(self.n + 1, dart); 
        //dart.embed = vec::from_elem(self.n + 1, );
        return dart;
    }

(非@mut解决方案所需的是"tying the knot",但我不清楚如何在Rust中实现它。)

1
这就是我现在学习 Rust 而不使用 Haskell 的原因。我发现图形结构从来没有感觉很对,总是需要一些技巧。再次感谢您的帮助。 - MFlamer
我猜我们需要使用letrec或lazy eval来解决这个问题。 - MFlamer
@MFlamer,通过futures可以实现惰性求值,但这是一种十分复杂的解决方案。 - huon
如果我在上面的函数中添加了这个语句 "self.darts.push(dart);",会怎么样呢?因为这是一个用于结构体的方法,特定实例可能是可变的或不可变的,Rust 如何决定是否可以改变 self? - MFlamer
明白了,pub fn new_dart(@mut self, ) -> @mut Dart<T> { - MFlamer
3
@MFlamer,“&mut self”也可以使用,并且略微更加灵活。 - huon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接