Нельзя заимствовать неизменяемый заимствованный контент как изменчивый
Я пытаюсь разработать приложение для маршрутизации сообщений. Я читал официальные документы Rust и некоторые статьи и думал, что у меня есть то, как указатели, владеющие и заимствованные вещи работают, но поняли, что я этого не сделал.
use std::collections::HashMap;
use std::vec::Vec;
struct Component {
address: &'static str,
available_workers: i32,
lang: i32
}
struct Components {
data: HashMap<i32, Vec<Component>>
}
impl Components {
fn new() -> Components {
Components {data: HashMap::new() }
}
fn addOrUpdate(&mut self, component: Component) -> &Components {
if !self.data.contains_key(&component.lang) {
self.data.insert(component.lang, vec![component]);
} else {
let mut q = self.data.get(&component.lang); // this extra line is required because of the error: borrowed value does not live long enough
let mut queue = q.as_mut().unwrap();
queue.remove(0);
queue.push(component);
}
self
}
}
(Также доступна на игровая площадка)
Выдает ошибку:
error: cannot borrow immutable borrowed content `**queue` as mutable
--> src/main.rs:26:13
|
26 | queue.remove(0);
| ^^^^^ cannot borrow as mutable
error: cannot borrow immutable borrowed content `**queue` as mutable
--> src/main.rs:27:13
|
27 | queue.push(component);
| ^^^^^ cannot borrow as mutable
Не могли бы вы объяснить ошибку, и было бы здорово, если бы вы могли дать мне правильную реализацию.
Ответы
Ответ 1
Ниже приведено небольшое сокращение вашей проблемы:
use std::collections::HashMap;
struct Components {
data: HashMap<u8, Vec<u8>>
}
impl Components {
fn add_or_update(&mut self, component: u8) {
let mut q = self.data.get(&component);
let mut queue = q.as_mut().unwrap();
queue.remove(0);
}
}
fn main() {}
Много раз, когда что-то кажется таким удивительным, полезно распечатать используемые типы. Выделите тип queue
:
let mut q: () = self.data.get(&component);
= note: expected type `()`
found type `&mut &std::vec::Vec<u8>`
У нас есть изменяемая ссылка на неизменяемую ссылку на Vec<u8>
. Поскольку мы имеем неизменную ссылку на Vec
, мы не можем ее изменить! Изменение self.data.get
на self.data.get_mut
изменяет тип на &mut &mut collections::vec::Vec<u8>
и компилирует код.
Если вы хотите реализовать концепцию "вставить или обновить", вы должны проверить в entry
API, что больше эффективный и лаконичный.
Кроме того, Rust использует snake_case
для наименования метода, а не camelCase
.