#rust
Вопрос:
Я довольно новичок в rust, и я застрял на том, что, вероятно, очень простой вопрос о заимствовании. Я упростил свой код, как показано ниже:
pub struct MyStruct {
pub val: i32
}
impl MyStruct {
pub fn new(val: i32) -> Self {
MyStruct {
val
}
}
}
pub struct MyStructVec {
pub vec: Vec::<MyStruct>
}
impl MyStructVec {
pub fn new() -> Self {
MyStructVec {
vec: Vec::new()
}
}
pub fn insert(amp;mut self, mut my_struct: MyStruct) {
self.vec.push(my_struct);
}
fn run(amp;mut self) {
for s in self.vec.iter_mut() {
s.val = s.val 1;
self.edit(s);
}
}
fn edit(amp;self, my_struct: amp;mut MyStruct) {
my_struct.val = my_struct.val * 2;
}
}
fn main() {
let mut my_struct1 = MyStruct::new(69);
let mut my_struct2 = MyStruct::new(420);
let mut my_struct_vec = MyStructVec::new();
my_struct_vec.insert(my_struct1);
my_struct_vec.insert(my_struct2);
my_struct_vec.run();
}
Когда я запускаю это, я получаю следующую ошибку:
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src/main.rs:33:13
|
31 | for s in self.vec.iter_mut() {
| -------------------
| |
| mutable borrow occurs here
| mutable borrow later used here
32 | s.val = s.val 1;
33 | self.edit(s);
| ^^^^ immutable borrow occurs here
Но если я отредактирую свой код следующим образом:
fn run(amp;mut self) {
for s in self.vec.iter_mut() {
s.val = s.val 1;
//self.edit(s);
s.val = s.val * 2;
}
}
Тогда он работает отлично. Это пример упрощенного случая, но в моем реальном коде я мог бы просто выделить свой код в отдельную функцию для удобства чтения, например, с помощью функции редактирования. Итак, каков правильный способ сделать это в Rust? Большое спасибо!
Комментарии:
1. Зачем
MyStructVec::edit
получать неизменяемую ссылку наself
, когда он ее не использует?2. «Возможно, я просто захочу выделить свой код в отдельную функцию для удобства чтения» — подпись функции — это ваш контракт с компилятором.
edit()
Функция говорит, что ей нужна ссылка на self , но вам также нужноself
одновременно изменять часть, что недопустимо. Если вам нужно что-то изself
при редактировании aMyStruct
, то у вас должна быть функция только с этими частями, чтобы они не могли конфликтовать. Разделение кода должно следовать за разделением контракта.
Ответ №1:
Я думаю, ошибка заключается в том, что по какой-то причине вы вносите MyStructVec
изменения MyStruct
, когда это может быть простой метод MyStruct
. Вы возитесь с большим количеством ссылок, которые вам нужны, и на самом деле вы не берете те, которые вам нужны. Кажется справедливым, что edit
это должно быть инкапсулировано в объект, который будет изменен:
impl MyStruct {
...
fn edit(amp;mut self) {
self.val = self.val * 2;
}
}
...
impl MyStructVec {
...
fn run(amp;mut self) {
for s in self.vec.iter_mut() {
s.val = s.val 1;
s.edit();
}
}
}