Joh*_*han 5 closures immutability traits rust
我有一个捕获并修改其环境的闭包。我想将此闭包传递给接受闭包的函数:
fn main() {
let mut integer = 5;
let mut closure_variable = || -> i32 {
integer += 1;
integer
};
execute_closure(&mut closure_variable);
}
fn execute_closure(closure_argument: &mut Fn() -> i32) {
let result = closure_argument();
println!("Result of closure: {}", result);
}
Run Code Online (Sandbox Code Playgroud)
因为闭包修改了它的环境,所以失败了:
fn main() {
let mut integer = 5;
let mut closure_variable = || -> i32 {
integer += 1;
integer
};
execute_closure(&mut closure_variable);
}
fn execute_closure(closure_argument: &mut Fn() -> i32) {
let result = closure_argument();
println!("Result of closure: {}", result);
}
Run Code Online (Sandbox Code Playgroud)
据我了解,闭包何时实现 Fn、FnMut 和 FnOnce?,这意味着我的闭包实际上扩展为实现该 Trait 的结构FnMut。此特征是可变的,这意味着调用该函数会更改(隐式)对象。integer我认为这是正确的,因为应该在调用后修改变量execute_closure()。
我如何说服编译器这是可以的并且我实际上想调用一个FnMut函数?或者我在这个例子中使用 Rust 的方式有什么根本性的错误吗?
接受 aFnMut而不是 a Fn:
fn main() {\n let mut integer = 5;\n execute_closure(|| {\n integer += 1;\n integer\n });\n}\n\nfn execute_closure<F>(mut closure_argument: F)\nwhere\n F: FnMut() -> i32,\n{\n let result = closure_argument();\n println!("Result of closure: {}", result);\n}\nRun Code Online (Sandbox Code Playgroud)\n\nuse std::cell::Cell;\n\nfn main() {\n let integer = Cell::new(5);\n execute_closure(|| {\n integer.set(integer.get() + 1);\n integer.get()\n });\n}\n\nfn execute_closure<F>(closure_argument: F)\nwhere\n F: Fn() -> i32,\n{\n let result = closure_argument();\n println!("Result of closure: {}", result);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n或者我在这个例子中使用 Rust 的方式有什么根本性的错误吗?
\n
也许。类型的参数&mut Fn() -> i32不能改变它所关闭的变量,因此错误消息对我来说是有意义的。
它类似于 \xe2\x80\x94 类型,您&mut &u8可以更改外部引用以指向另一个不可变引用,但您不能“忽略”内部不可变性并更改数值。
在旁边:
\n\n原始代码使用动态调度,因为有一个提供间接性的特征对象。在许多情况下,您会看到我上面发布的这个版本,它使用静态调度并且可以单态化。我还内联了闭包,因为这是正常的语法。
\n\n这是原始版本,做了足够的更改即可工作:
\n\nfn main() {\n let mut integer = 5;\n let mut closure_variable = || -> i32 {\n integer += 1;\n integer\n };\n execute_closure(&mut closure_variable);\n}\n\nfn execute_closure(closure_argument: &mut FnMut() -> i32) {\n let result = closure_argument();\n println!("Result of closure: {}", result);\n}\nRun Code Online (Sandbox Code Playgroud)\n