如何在选项为 None 时结束借入
How to end borrow when an Option is None
以下代码将使借用检查器失败:
fn at(&mut self, i: usize) -> Option<&T> {
match self.vector.get(i) {
Some(x) => Some(x),
None => {
self.mutate_vector_to_have_more_stuff();
self.at(i)
}
}
}
我明白为什么了:self.vector
仍然是借用到最后的词汇,所以我不能再借用 self
。
构建范围的正确方法是什么?借用持续存在于匹配中,因为我实际上在 Some(x)
分支中使用它,但在 None
分支中我不再使用借用的值,因为开始时没有借用的值。
我有一个适用于这个特定案例的重写版本:
if i >= self.vector.len() {
self.mutate_vector_to_have_more_stuff();
self.at(i)
} else {
self.vector.get(i)
}
这是有效的,因为使用 len
意味着我在尝试借用任何东西之前就见证了 "nothing to borrow",然后只在嵌套范围内借用。我担心这在我有一个 Option
的所有情况下都不起作用,但是,每个 Option
返回的 API 可能没有一个纯布尔变量。
有没有一种方法可以重构此代码使其正常工作,但仍使用 get
调用作为了解是否存在值的主要方式?
由于当前在(稳定的)Rust 中的生命周期工作方式,这是一个常见问题。在您的情况下,标准解决方案看起来像这样:
fn at(&mut self, i: usize) -> Option<&T> {
if let Some(x) = self.vector.get(i) {
return Some(x);
}
// mutate self.vector
self.at(i)
}
正如您可能看到的那样,self.vector
的不可变借用仅持续到 if 块,因此可以尽快对其进行可变借用结束了。
也就是说,如果您想启用不稳定的 non-lexical lifetimes 功能,Rust nightly 可以解决此问题。如果您只在 crate 顶部包含 #![feature(nll)]
行,您现有的代码应该可以正常工作。
以下代码将使借用检查器失败:
fn at(&mut self, i: usize) -> Option<&T> {
match self.vector.get(i) {
Some(x) => Some(x),
None => {
self.mutate_vector_to_have_more_stuff();
self.at(i)
}
}
}
我明白为什么了:self.vector
仍然是借用到最后的词汇,所以我不能再借用 self
。
构建范围的正确方法是什么?借用持续存在于匹配中,因为我实际上在 Some(x)
分支中使用它,但在 None
分支中我不再使用借用的值,因为开始时没有借用的值。
我有一个适用于这个特定案例的重写版本:
if i >= self.vector.len() {
self.mutate_vector_to_have_more_stuff();
self.at(i)
} else {
self.vector.get(i)
}
这是有效的,因为使用 len
意味着我在尝试借用任何东西之前就见证了 "nothing to borrow",然后只在嵌套范围内借用。我担心这在我有一个 Option
的所有情况下都不起作用,但是,每个 Option
返回的 API 可能没有一个纯布尔变量。
有没有一种方法可以重构此代码使其正常工作,但仍使用 get
调用作为了解是否存在值的主要方式?
由于当前在(稳定的)Rust 中的生命周期工作方式,这是一个常见问题。在您的情况下,标准解决方案看起来像这样:
fn at(&mut self, i: usize) -> Option<&T> {
if let Some(x) = self.vector.get(i) {
return Some(x);
}
// mutate self.vector
self.at(i)
}
正如您可能看到的那样,self.vector
的不可变借用仅持续到 if 块,因此可以尽快对其进行可变借用结束了。
也就是说,如果您想启用不稳定的 non-lexical lifetimes 功能,Rust nightly 可以解决此问题。如果您只在 crate 顶部包含 #![feature(nll)]
行,您现有的代码应该可以正常工作。