我有一些像这样的代码:防止忘记调用一个方法
foo.move_right_by(10);
//do some stuff
foo.move_left_by(10);
这真的很重要,我的那些操作最终的同时执行,但我常常忘记做第二第一个之后。它导致了很多错误,我想知道是否有一种习惯性的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()'也被调用?另外:你可以描述封闭功能吗?它会返回任何东西吗? –
OP,如果在调用move_right()后必须调用'move_left()',则可以将这些功能打包以返回自动调用'move_left()'的Drop类型的自定义类型 - 尽管如果你的第二个FN必须返回值等等,这可能是不可能的......这可能是一个想法,但它可能会很快变得丑陋。 – musicmatze
如果你可以表示一系列调用作为一个状态机来执行,那么状态可以被编码为类型,并在'self'上进行方法调用(消耗当前状态并产生一个新状态)。这是可能的,还是不够灵活? –