Итак, у меня есть вышеуказанная ошибка в строке 17, которую я понимаю, но не нашел хорошего способа ее решения:
struct Node {
node_type: NodeType
}
enum NodeType {
Inner([Box<Node>; 16]),
Leaf(Vec<usize>)
}
impl Node {
fn foo(&mut self) {
match &mut self.node_type {
NodeType::Leaf(_content) => {
// Mutate content
},
NodeType::Inner(children) => {
let index = self.compute_index();
let child = &mut children[index];
child.foo();
}
}
}
fn compute_index(&self) -> usize {
// compute something
0
}
}
Мне нужно, чтобы self
был изменяемым, чтобы изменять его содержимое в случае Leaf
. Я мог бы скопировать код из compute_index()
в свою функцию foo()
, но это сделало бы функцию foo()
излишне длинной, и код внутри compute_index()
сам по себе будет выглядеть как отдельная семантическая единица.
Я также мог бы переместить вызов в compute_index()
над оператором match
, но мне не нужно выполнять его во всех ответвлениях сопоставления, поэтому в этом случае это приведет к ненужным вычислениям и тоже не кажется правильным.
Я думал об этом довольно долго, но не мог придумать, как избавиться от этой ошибки, не ухудшив при этом свой код. Есть ли у кого-нибудь идеи, как избавиться от ошибки, не ухудшив код?
Нет
Тогда вы можете сделать так, чтобы он занимал только необходимые поля, а не все self
. В качестве альтернативы, если это имеет больше смысла, разделите структуру NonChildren
на Node
и сделайте compute_index()
методом NonChildren
.
Можете ли вы перетасовать все, чтобы вычислить индекс, прежде чем получать изменяемый заем?
impl Node {
fn foo(&mut self) {
if let NodeType::Leaf(_content) = &mut self.node_type {
// Mutate content
_content.push(42);
} else {
let index = self.compute_index();
if let NodeType::Inner(children) = &mut self.node_type {
let child = &mut children[index];
child.foo();
}
}
}
fn compute_index(&self) -> usize {
// compute something
0
}
}
Да, это хорошо работает. Второе if let кажется немного ненужным, поскольку вы уже знаете, что это Inner, но это кажется лучшим решением, спасибо! :)
Проблема match
в том, что он держит нагрузку на все тело. Возможно, вы также можете сохранить совпадение как есть и условно вычислить индекс перед совпадением с помощью let index = if let NodeType::Inner(_) = self.node_type { self.compute_index() } else { 0 };
и использовать индекс только в одной ветви сопоставления, но это своего рода утечка инкапсуляции.
Верно, но я предпочитаю ваше оригинальное решение, потому что мне не нравится объявлять переменные в более широкой области, чем они используются/необходимы.
Зависит ли
compute_index()
отchildren
?