Rust 也支持闭包。闭包与函数类似,但具有声明它们的环境或作用域的更多信息。

    let my_closure = || ();。我们刚刚定义了一个什么都不做的无参数闭包,然后我们可以通过my_closure()来调用它,这和函数类似。两个竖条||用于存放闭包的参数(如果有的话),例如|a,b|。当Rust无法找出正确的类型时,有时需要指定参数类型|a:u32|。和函数类似,闭包也可以储存在变量中,稍后调用或传递给其他函数。但是,闭包主题也可以是单一表达式,也可以是由花括号标识的多个表达式组成。更复杂的闭包:

    1. fn main() {
    2. let doubler = |x| x * 2;
    3. let value = 5;
    4. let twice = doubler(value);
    5. println!("{} doubled is {}",value,twice);
    6. let big_closure = |b,c| {
    7. let z = b + c;
    8. z * twice
    9. };
    10. let some_number = big_closure(1,2);
    11. println!("Result from closure: {}",some_number);
    12. }

    在上述代码中,我们定义了两个闭包:doublerbig_closure

    • doubler将给定的值加倍。在这种情况下它从父作用域或上下文环境传递value,即main函数。
    • big_closure中,我们从其环境中使用变量 twice。这个闭包在花括号内有多行表达式,需要以分号结尾。以便我们将它分配给变量big_closure。之后,我们调用big_closure,传入1、2作为参数并输出 some_number

    闭包主要用作高阶函数的参数。高阶函数是一个以另一个函数或闭包作为参数的函数。

    例如:标准库中的thread::spawn函数接收一个闭包作为参数,你可以在其中编写要在另一个线程中运行的代码。。

    闭包提供简便、抽象的另一个场景是,当你有一个对 Vec 等集合进 行操作的函数时,希望根据某些条件过滤元素。Rust 的迭代器特征(iterator trait)有一个 名为 filter 的方法,可以接收一个闭包作为参数。

    1. let numbers = vec![1, 2, 3, 4, 5];
    2. let even_numbers = numbers.into_iter().filter(|x| x % 2 == 0).collect::<Vec<_>>();
    • |x| x % 2 == 0 是一个闭包,它接受迭代器中的当前元素 x 作为参数。闭包体 x % 2 == 0 检查 x 是否是偶数(即 x 除以 2 的余数是否为 0)。
    • 如果闭包返回 true,则当前元素会被保留在过滤后的迭代器中;如果返回 false,则当前元素被过滤掉。
    • 因此,.filter(|x| x % 2 == 0) 的作用是从原始集合中筛选出所有偶数。

    下面是在编译器中闭包的显示:

    闭包 - 图1

    其实闭包就是把一个函数绑定了变量,然后可以通过变量来使用该函数。