不能借用可变的借项,因为它在`&`引用后面

时间:2019-08-09 21:22:32

标签: rust

为了更好地了解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的情况下总是返回可变引用的情况下进行此操作,因为在所有其他情况下,我都在调用{{1 }}读取一行,而不是将其写入。

2 个答案:

答案 0 :(得分:2)

这是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允许您免费获取。
  • 使用u16没有多大意义,因为Vec是使用usize进行索引的。除非您确实想提供硬编码的限制,否则在这里使用u16是任意的。在那种情况下,我不会依赖类型的最大值,而是会使用一个常量来使意图更清晰。

答案 1 :(得分:1)

您想要的是不可能的。您将必须编写两个函数(请注意,我将u16替换为usize-没有理由将自己限制为每行65536个字符):

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

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

请注意,这是所有Rust代码中的通用模式。例如,Vec具有get(idx)get_mut(idx)