我想要一个带有函数的向量。然后我想迭代这个向量并逐个执行函数。这些函数会改变外部状态。另外,我希望能够在向量中放置两次相同的函数。
我遇到的问题是:
我最接近的是:
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);
}
答案 0 :(得分:3)
对于第一个问题,我真的不知道为什么在这里没有发生可变的解引用(在我看来,它应该),但是有一个简单的解决方法:只需进行取消引用然后手动引用:
(&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()
,它可以自由别名,并且其捕获的环境也可能包含别名引用(当然是不可变的)。