闭包只有这三种模式,即
Fn:它只能从闭包环境中不可变借用相关变量;
FnMut:它能可变借用捕获的变量,并改变闭包环境;
FnOnce:它捕获的闭包环境变量,闭包本身只能用一次,不是说闭包中的变量被一次性消费,而是指闭包本身;
为什么会引出Fn,FnMut,FnOnce?
如果1:
let example_closure = |x| x;
let s = example_closure(String::from("hello"));
let n = example_closure(5);//默认为String才能通过,那为什么i32不行?
如果2:
let example_closure = |x| x;
let n = example_closure(5);//默认为i32才能通过,那为什么String不行?
let s = example_closure(String::from("hello"));
这种情况,就需要更精确地定义闭包。对参数的形式,要给编译器提示清楚。
1、FnOnce:
fn consume_with_relish<F>(func: F)
where F: FnOnce() -> String
{
// `func` consumes its captured variables, so it cannot be run more
// than once.
println!("Consumed: {}", func());
println!("Delicious!");
// Attempting to invoke `func()` again will throw a `use of moved
// value` error for `func`.
}
let x = String::from("x");
let consume_and_return_x = move || x;
consume_with_relish(consume_and_return_x);
// `consume_and_return_x` can no longer be invoked at this point
2、FnMut:
fn do_twice<F>(mut func: F) //少了mut会报错!
where F: FnMut()
{
func();
func();
}
let mut x: usize = 1;
{
let add_two_to_x = || x += 2;
do_twice(add_two_to_x);
}
assert_eq!(x, 5); // 闭包改变了变量x,1=>3=>5
3、Fn
fn call_with_one<F>(func: F) -> usize
where F: Fn(usize) -> usize {
func(1)
}
let double = |x| x * 2;
assert_eq!(call_with_one(double), 2);