#rust
#Ржавчина
Вопрос:
Этот вопрос, вероятно, будет действительно простым, но я даже не знаю, что искать. Я не видел ничего, что бросилось мне в глаза в книге, и я новичок в Rust:
struct Node;
impl Node {
fn children(amp;mut self) -> amp;mut Vec<Node> {
// Pulls a field out of Node, to be mutated
}
fn next_node(amp;self) -> Node {
// Produces a new value using values computed from self.
// Doesn't hold a reference to self
}
}
[...]
if self.children().len() > K {
let mut next_node = self.next_node();
let list = self.children();
// something involving next_node and list
}
Это то, что я в конечном итоге получил, чтобы убедить Rust, что то, что я делал, было в порядке.
То, что я нашел более простым, было:
let list = self.children();
if list.len() > K {
let mut next_node = self.next_node();
// Something involving next_node and list
}
Но он жаловался, потому что я не мог получить неизменяемую ссылку на self
in next_node
, потому что уже была изменяемая ссылка, содержащаяся в self.children
, что верно.
В частности, в этой реализации я делаю это только .children()
один раз, что в данном случае не является очень сложным методом, но может быть.
Есть ли способ сделать это, который не вычисляет children
более одного раза и не создает next_node
, когда это не требуется?
Ответ №1:
Простой ответ: нет.
Rust может указывать на непересекающиеся поля при заимствовании, поэтому вы можете изменяемо заимствовать поле, а затем заимствовать другое поле, и это будет работать, если оба они встречаются в одном контексте (функция / метод).
В этом случае то, что next_node
делает, непрозрачно для компилятора, и, насколько нам известно, он может фактически использовать дочерние элементы.
Таким образом, требуется, чтобы при вызове next_node
не было изменяемого заимствования.
В частности, в этой реализации я делаю это только
.children()
один раз, что в данном случае не является очень сложным методом, но может быть.
Верно… но какова ответственность этого метода. Зачем ему выполнять как обширные вычисления, так и заимствования?
Более простая организация этого кода будет:
- выполните дорогостоящее вычисление один раз (не заимствуя)
- заимствуйте как можно меньшую область
и это сработало бы:
self.expensive_computation();
if self.children.len() > K {
let mut next_node = self.next_node();
let list = self.children;
// Something involving next_node and list
}