我想要一个带有函数的向量。然后我想迭代这个向量并一个一个地执行函数。这些函数会改变外部状态。此外,我希望能够在向量中放置两次相同的函数。
我遇到的问题是:
- 我无法取消引用并执行向量中的函数,
- 将相同的函数添加到 vector 两次都失败了,这是可以理解的错误,我不能有两个可变引用。
我得到的最接近的是:
fn main() {
let mut c = 0;
{
let mut f = ||{c += 1};
let mut v: Vec<&mut FnMut()> = vec![];
v.push(&mut f);
// How to execute the stored function? The following complains about
// an immutable reference:
// assignment into an immutable reference
// (v[0])();
// How to store the same function twice? The following will fail with:
// cannot borrow `f` as mutable more than once at a time
// v.push(&mut f);
}
println!("c {}", c);
}
最佳答案
对于第一个问题,我真的不知道为什么这里没有发生可变的取消引用(在我看来,它应该),但有一个简单的解决方法:只需执行取消引用然后手动引用:
(&mut *v[0])();
不过,您的第二个问题更复杂。没有简单的解决方案,因为您尝试做的事情违反了 Rust 别名保证,并且由于您没有描述它的目的,所以我无法正确建议替代方案。但是,一般来说,您可以通过使用 Cell
/RefCell
或 Mutex
切换到运行时借用检查来克服此错误(后者是当您需要并发访问)。使用 Cell
(适用于原语):
use std::cell::Cell;
fn main() {
let c = Cell::new(0);
{
let f = || { c.set(c.get() + 1); };
let mut v: Vec<&Fn()> = vec![];
v.push(&f);
v.push(&f);
v[0]();
v[1]();
}
println!("c {}", c.get());
}
使用 RefCell
(适用于更复杂的类型):
use std::cell::RefCell;
fn main() {
let c = RefCell::new(0);
{
let f = || { *c.borrow_mut() += 1; };
let mut v: Vec<&Fn()> = vec![];
v.push(&f);
v.push(&f);
v[0]();
v[1]();
}
println!("c {}", *c.borrow());
}
如您所见,现在您有 &Fn()
而不是 &mut FnMut()
,它可以自由别名,并且其捕获的环境也可能包含别名引用(当然是不可变的)。
关于rust - 持有可变函数的向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49395257/