假设我有那些结构体(没有花哨的指针,一切都是可复制的)
#[derive(Debug, Copy, Clone)]
struct Item {
id: u32,
pub value: u32
}
我可以创建一个struct来保存这样的项目的vec:
#[derive(Debug)]
struct Container {
next_id: u32,
items: Vec<Item>
}
如果你知道确切的位置,添加元素和更改它们是相当容易的:
impl Container {
fn new() -> Container {
Container {
next_id: 0,
items: vec!()
}
}
fn add(&mut self) -> u32 {
let id = self.next_id;
self.items.push(Item {
id: self.next_id,
value: 0
});
self.next_id = self.next_id + 1;
id
}
fn lookup(&mut self, id: u32) -> Option<&Item> {
self.items.iter().find(|item| item.id == id)
}
fn change_first(&mut self, new_value: u32) {
if self.items.len() < 0 {
panic!("No item to change");
}
self.items[0].value = new_value;
}
}
这使得这样的测试通过:
#[test]
fn can_change_first() {
let mut c = Container::new();
assert_eq!(c.add(), 0);
c.change_first(22);
assert_eq!(c.lookup(0).unwrap().value, 22);
}
但是,假设我想查找和元素并找到它.我不想直接公开items
vec,但建议使用一个API:
#[test]
fn can_lookup_and_change() {
let mut c = Container::new();
assert_eq!(c.add(), 0);
c.change_at(0, 22);
assert_eq!(c.lookup(0).unwrap().value, 22);
}
change_at
的简单实现是:
fn change_at(&mut self, id: u32, new_value: u32) {
let lookup = self.lookup(id);
match lookup {
Some(item) => {
item.value = new_value;
}
None => {
// ...
}
}
}
但是,编译器不接受它,并给出错误:
Compiling web v0.1.0 (/home/phtrivier/perso/prj/wirth/dom-web)
error[E0594]: cannot assign to `item.value`, which is behind a `&` reference
--> redacted/src/lib.rs:170:17
|
169 | Some(item) => {
| ---- consider changing this binding's type to be: `&mut Item`
170 | item.value = new_value;
| ^^^^^^^^^^^^^^^^^^^^^^ `item` is a `&` reference, so the data it refers to cannot be written
For more information about this error, try `rustc --explain E0594`.
我不明白错误是否在lookup
端(是否有不同的方法来查找项目,使他们静音?)或change_at
端(这是模式匹配的正确方法吗?)
1条答案
按热度按时间xsuvu9jc1#
您可以添加一个
lookup_mut
方法。这将用iter_mut
替换iter
。然后在需要可变引用时使用它。