У меня есть такой код:
foo.move_right_by(10);
//do some stuff
foo.move_left_by(10);
Очень важно выполнять обе эти операции в конце концов, но я часто забываю сделать вторую после первой. Это вызывает много ошибок, и мне интересно, есть ли идиоматический способ Rust избежать этой проблемы. Есть ли способ заставить компилятор rust сообщать мне, когда я забуду?
Моя идея заключалась в том, чтобы как-то иметь что-то вроде этого:
// must_use will prevent us from forgetting this if it is returned by a function
#[must_use]
pub struct MustGoLeft {
steps: usize;
}
impl MustGoLeft {
fn move(&self, foo: &mut Foo) {
foo.move_left_by(self.steps);
}
}
// If we don't use left, we'll get a warning about an unused variable
let left = foo.move_left_by(10);
// Downside: move() can be called multiple times which is still a bug
// Downside: left is still available after this call, it would be nice if it could be dropped when move is called
left.move();
Есть ли лучший способ сделать это?
Другая идея состоит в том, чтобы реализовать Drop
и panic!
, если структура удаляется без вызова этого метода. Это не так хорошо, потому что это проверка во время выполнения, а это крайне нежелательно.
Изменить: я понял, что мой пример может быть слишком простым. Используемая логика может стать довольно сложной. Например, у нас есть что-то вроде этого:
foo.move_right_by(10);
foo.open_box(); // like a cardboard box, nothing to do with Box<T>
foo.move_left_by(10);
// do more stuff...
foo.close_box();
Обратите внимание, что операции выполняются не в правильном, правильно вложенном порядке. Единственное, что важно, это то, что обратная операция всегда вызывается после. Иногда необходимо указать порядок определенным образом, чтобы код работал должным образом.
У нас может быть даже что-то вроде этого:
foo.move_right_by(10);
foo.open_box(); // like a cardboard box, nothing to do with Box<T>
foo.move_left_by(10);
// do more stuff...
foo.move_right_by(10);
foo.close_box();
foo.move_left_by(10);
// do more stuff...
move_right()
, то иmove_left()
тоже вызывается? Также: можете ли вы описать закрывающую функцию? Возвращает что-нибудь? - person Lukas Kalbertodt   schedule 04.02.2017move_left()
после вызоваmove_right()
, вы можете связать эти функции, чтобы вернуть пользовательский тип (своего рода обработчик), который автоматически вызываетmove_left()
наDrop
— хотя это может быть невозможно, если ваш второй fn должен возвращать значения и так далее... Это может быть идеей, но она может довольно быстро стать уродливой. - person musicmatze   schedule 04.02.2017self
(которые потребляют текущее состояние и создают новое). Возможно ли это или недостаточно гибко? - person Matthieu M.   schedule 04.02.2017