我有以下结构表示数字计算的计划:
pub struct NfftPlan<'a> {
x: Option<&'a [f64]>,
f_hat: Option<&'a [Complex64]>,
// ...
}
它有一个set_f_hat
方法:
pub fn set_f_hat(&mut self, f_hat: &'a [Complex64]) {
self.f_hat = Some(f_hat);
}
和一个执行
方法:
pub fn execute(&self) -> Vec<Complex64>
不变地使用 f_hat
。
我想按以下方式使用它:
let mut f_hat = vec![1,2,3,4];
let plan = NfftPlan::new()
plan.set_f_hat(&f_hat);
plan.execute();
f_hat[0] = 3; // Change f_hat to a new value
plan.execute(); //New computation
这失败了,因为我无法在 plan
仍然存在的情况下改变 f_hat
。
有没有办法让 plan
释放对 f_hat
的借用,这样我就可以改变 f_hat
向量?
像这样:
releasedata(&self) {
self.f_hat = None
} //Now the compiler forgets that plan would hold an borrow to f_hat
我知道 Rust 不允许我在借用向量时更改向量,在这种情况下,通过 NfftPlan
结构中的 f_hat
引用。
我想要一种方法告诉编译器在 NfftPlan
结构中删除对向量的引用,而不删除整个结构。
最佳答案
说明
How can I tell the compiler to release a borrow
你不能,句号。这不是您“告诉”编译器的事情,编译器什么都知道。您只能完全停止使用该引用。
without dropping the entire struct
丢弃 不会清除借用,只有不再使用的借用才会清除,这可能会因丢弃而发生。
f_hat[0] = 3; // Change f_hat to a new value plan.execute(); //New computation
这正是 Rust 试图阻止的代码类型之一。 plan.execute()
应该返回一个不同的值一点也不明显,因为一些明显无关的值发生了变化。
解决方案
在类型系统中编码
我会构建我的类型以反射(reflect)它们需要如何使用,创建一次性值,这些值只有在所有内容组合在一起后才能执行。这意味着借用 f_mut
的结构一完成就被丢弃;请注意这是如何完全删除 Option
的:
fn main() {
let mut f_hat = 42;
let plan = Plan::default();
plan.set_f_hat(&f_hat).execute();
f_hat = 3;
plan.set_f_hat(&f_hat).execute();
}
#[derive(Debug, Default)]
struct Plan<'a> {
x: Option<&'a i32>,
}
impl<'a> Plan<'a> {
fn set_f_hat(&self, f_hat: &'a i32) -> PlanPlus<'a> {
PlanPlus { x: self.x, f_hat }
}
}
#[derive(Debug)]
struct PlanPlus<'a> {
x: Option<&'a i32>,
f_hat: &'a i32,
}
impl<'a> PlanPlus<'a> {
fn execute(&self) {}
}
使用内部可变性和引用计数
use std::{cell::Cell, rc::Rc};
#[derive(Debug, Default)]
struct Plan<'a> {
x: Option<&'a i32>,
f_hat: Option<Rc<Cell<i32>>>,
}
impl<'a> Plan<'a> {
fn set_f_hat(&mut self, f_hat: Rc<Cell<i32>>) {
self.f_hat = Some(f_hat);
}
fn execute(&self) {}
}
fn main() {
let f_hat = Rc::new(Cell::new(42));
let mut plan = Plan::default();
plan.set_f_hat(f_hat.clone());
plan.execute();
f_hat.set(3);
plan.execute();
}
识别成员是可变的
#[derive(Debug, Default)]
struct Plan<'a> {
x: Option<&'a i32>,
f_hat: Option<&'a mut i32>,
}
impl<'a> Plan<'a> {
fn f_hat(&mut self) -> &mut Option<&'a mut i32> {
&mut self.f_hat
}
fn execute(&self) {}
}
fn main() {
let mut f_hat = 42;
let mut plan = Plan::default();
*plan.f_hat() = Some(&mut f_hat);
plan.execute();
**plan.f_hat().as_mut().unwrap() = 3;
plan.execute();
}
另见:
关于rust - 我如何告诉编译器在不删除整个结构的情况下释放结构中的借用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57694567/