闭包状态中有一些数据,但是如何使它可变?例如,我想要一个计数器关闭,每次都返回递增的值,但是它不起作用。我该如何运作?
fn counter() -> Box<Fn() -> i32> {
let mut c: i32 = 0;
Box::new(move || {
c += 1;
c
})
}
fn main() {
let mut a = counter();
let mut b = counter();
println!("{:?}", [a(), a(), a(), b(), b(), a()]);
}
错误(和警告),我得到:
error: cannot assign to captured outer variable in an `Fn` closure
c += 1;
^~~~~~
help: consider changing this closure to take self by mutable reference
Box::new(move || {
c += 1;
c
})
我希望它输出类似的内容[1, 2, 3, 1, 2, 4]
。
如错误消息所述:
无法在
Fn
闭包中分配给捕获的外部变量
相反,您需要一个FnMut
闭包:
fn counter() -> Box<FnMut() -> i32> {
let mut c = 0;
Box::new(move || {
c += 1;
c
})
}
fn main() {
let mut a = counter();
let mut b = counter();
let result = [a(), a(), a(), b(), b(), a()];
println!("{:?}", result);
assert_eq!([1, 2, 3, 1, 2, 4], result);
}
正如FnMut
文档所说:
带有可变接收方的呼叫操作员版本。
这允许闭包使包含的状态发生突变。
顺便说一句,c
不需要for的显式类型。
使我感到困惑的是
pub trait Fn<Args>: FnMut<Args>
。这不是意味着Fn
(我用过的)应该支持的行为FnMut
吗?
也许闭包何时实现Fn,FnMut和FnOnce?可以帮助提供一些背景信息。这是我凭直觉获得的一个方面,但是还没有弄清楚如何最好地进行交流。查找Rust中的闭包的这一部分似乎也很相关:
从高层次
self
上讲,实现者(即用户为实现特征而定义的类型)具有最大的灵活性,而&mut self
下一个则灵活性&self
最小。相反,&self
使特性(即具有受特性限制的泛型的函数)的使用者具有最大的灵活性,而self
最小的灵活性。
简而言之,该特征定义表明任何FnMut
闭包都可以用作Fn
闭包。这很有意义,因为我们可以简单地忽略可变性。您不能采用其他方式-您不能将可变引用作为可变引用。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句