Rust 也支持闭包。闭包与函数类似,但具有声明它们的环境或作用域的更多信息。
let my_closure = || ();
。我们刚刚定义了一个什么都不做的无参数闭包,然后我们可以通过my_closure()
来调用它,这和函数类似。两个竖条||
用于存放闭包的参数(如果有的话),例如|a,b|
。当Rust
无法找出正确的类型时,有时需要指定参数类型|a:u32|
。和函数类似,闭包也可以储存在变量中,稍后调用或传递给其他函数。但是,闭包主题也可以是单一表达式,也可以是由花括号标识的多个表达式组成。更复杂的闭包:
fn main() {
let doubler = |x| x * 2;
let value = 5;
let twice = doubler(value);
println!("{} doubled is {}",value,twice);
let big_closure = |b,c| {
let z = b + c;
z * twice
};
let some_number = big_closure(1,2);
println!("Result from closure: {}",some_number);
}
在上述代码中,我们定义了两个闭包:doubler
和big_closure
。
doubler
将给定的值加倍。在这种情况下它从父作用域或上下文环境传递value,即main
函数。- 在
big_closure
中,我们从其环境中使用变量 twice。这个闭包在花括号内有多行表达式,需要以分号结尾。以便我们将它分配给变量big_closure
。之后,我们调用big_closure
,传入1、2作为参数并输出some_number
。
闭包主要用作高阶函数的参数。高阶函数是一个以另一个函数或闭包作为参数的函数。
例如:标准库中的thread::spawn
函数接收一个闭包作为参数,你可以在其中编写要在另一个线程中运行的代码。。
闭包提供简便、抽象的另一个场景是,当你有一个对 Vec 等集合进 行操作的函数时,希望根据某些条件过滤元素。Rust 的迭代器特征(iterator trait)有一个 名为 filter 的方法,可以接收一个闭包作为参数。
let numbers = vec![1, 2, 3, 4, 5];
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) 的作用是从原始集合中筛选出所有偶数。
下面是在编译器中闭包的显示:
其实闭包就是把一个函数绑定了变量,然后可以通过变量来使用该函数。