闭包( Closure ) 的出现其实是 程序员偷懒的结果,也可以说是 语言开发者为程序员送的福利。
为什么这么说呢 ?
我们来看看几个 闭包 的解释:
- 闭包就是在一个函数内创建立即调用的另一个函数。
- 闭包是一个匿名函数。也就是没有函数名称。
- 闭包虽然没有函数名,但可以把整个闭包赋值一个变量,通过调用该变量来完成闭包的调用。从某些方面说,这个变量就是函数名的作用。
- 闭包不用声明返回值,但它却可以有返回值。并且使用最后一条语句的执行结果作为返回值。闭包的返回值可以赋值给变量。
- 闭包有时候有些地方又称之为 内联函数。这种特性使得闭包可以访问外层函数里的变量。
从上面的描述中可以看出,闭包就是函数内部的一个没有函数名的内联函数。对于那些只使用一次的函数,使用闭包是最佳的代替方案。
定义闭包的语法
在介绍如何定义闭包前,我们先来看看 如何定义一个普通的函数。
一个普通的函数的定义语法格式如下
fn function_name(parameters) -> return_type {
// 函数的具体逻辑
}
从上面的描述中我们知道,闭包是一个没有函数名的内联函数。它的定义语法如下
|parameter| {
// 闭包的具体逻辑
}
从语法格式上来看,闭包就是普通函数去掉 fn 关键字,去掉函数名,去掉返回值声明,并把一对小括号改成一对 竖线 ||。
闭包的参数是可选的,如果一个闭包没有参数,那么它的定义语法格式如下
||{
// 闭包的具体逻辑
}
闭包虽然没有名称,但我们可以将闭包赋值给一个变量,然后就可以通过调用这个变量来完成闭包的调用。
let closure_function = |parameter| {
// 闭包的具体逻辑
}
因为调用闭包的语法实现了 Fn 特质,因此我们可以像调用普通函数那样,使用小括号 () 来调用闭包
closure_function(parameter); //invoking
范例:普通的闭包
下面的代码我们定义了一个闭包用于判断传递的参数是否偶数,并把闭包赋值给变量 is_even。
然后我们通过调用 is_even() 来完成闭包的调用。
fn main(){
let is_even = |x| {
x%2==0
};
let no = 13;
println!("{} is even ? {}",no,is_even(no));
}
编译运行以上 Rust 代码,输出结果如下
13 is even ? false
范例:闭包使用外部函数可以访问的变量
闭包还可以访问它所在的外部函数可以访问的所有变量。
fn main(){
let val = 10;
// 访问外层作用域变量 val
let closure2 = |x| {
x + val // 内联函数访问外层作用域变量
};
println!("{}",closure2(2));
}
编译运行以上 Rust 代码,输出结果如下
12