rust 不能借用为可变的,因为它位于"&“引用之后

qrjkbowd  于 2023-01-26  发布在  其他
关注(0)|答案(3)|浏览(134)

为了更好地了解Rust,我构建了一个简单的文本编辑器,并使用了以下结构体:

struct File {
    rows: Vec<Row>,
    filename: Option<String>
}

impl File {
    fn row(&self, index: u16) -> &Row{
        &self.rows[index as usize]
    }

}

struct Row {
    string: String,
}

struct EditorState {
    file: File,
}

正如您所看到的,我将编辑器的状态保存在一个结构体中,该结构体引用文件,该结构体包含许多行,该结构体包含一个字符串(这些结构体中的每一个都有更多的字段,但我已经删除了与问题无关的字段)
现在我想使我的行可编辑,并添加了以下内容:

impl Row {
    fn insert(&mut self, at: u16, c: char) {
        let at = at as usize;
        if at >= self.string.len() {
            self.string.push(c);
        } else {
            self.string.insert(at, c)
        }
    }
}

下面是我尝试更新行的方法:

//In the actual functon, I am capturing the keypress,
//get the correct row from the state and pass it and the pressed
// char to row.insert
fn update_row(mut state: &mut EditorState)  {
let row = &state.file.row(0);
row.insert(0, 'a');

}

以下代码无法编译:

error[E0596]: cannot borrow `*row` as mutable, as it is behind a `&` reference

从这个错误中,我可以看出问题在于Row应该是可变的,以便我可以编辑它(这是有意义的,因为我正在修改它的String)我不知道a)如何能够修改这里的字符串,以及b)如何在不使row总是返回可变引用的情况下做到这一点,就像在所有其他情况下一样,我调用row来读取一行,而不是去写。

ie3xauqp

ie3xauqp1#

下面是File的一个更惯用的实现:

impl File {
    fn row(&self, index: usize) -> Option<&Row> {
        self.rows.get(index)
    }

    fn row_mut(&mut self, index: usize) -> Option<&mut Row> {
        self.rows.get_mut(index)
    }
}

此处的注意事项:

  • 如果index超出界限,您的实现将出现异常。处理这种情况的惯用方法是返回一个Option,getget_mut允许您免费获得该Option。
  • 使用u16没有多大意义,因为Vec是使用usize索引的。使用u16在这里是任意的,除非你真的想提供硬编码的限制。在这种情况下,我不会依赖类型的max值,而是一个常量,这样会使意图更清楚。
xe55xuns

xe55xuns2#

你想要的是不可能的,你必须写两个函数(注意,我用usize代替了u16--你没有理由把自己限制在每行65536个字符):

fn row(&self, index: usize) -> &Row {
    &self.rows[index]
}

fn row_mut(&mut self, index: usize) -> &mut Row {
    &mut self.rows[index]
}

注意,这是所有Rust代码的共同模式,例如Vecget(idx)get_mut(idx)

lrl1mhuk

lrl1mhuk3#

文件封装行,因此不公开该行。
而是在File中实现方法以对封装的行执行某些操作。
一般来说,程序应该具有如下结构

object.do_something()

在您情况下:

file.do_something_with_row(x)

代替

let mut row = file.row_mut()
// do something with row here, rows leaking all over the place.

相关问题