Rust:Fn,FnMut,FnOnce

闭包只有这三种模式,即
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);

猜你喜欢

转载自blog.csdn.net/wowotuo/article/details/80785358