Rust 闭包


快速掌握Rust闭包

闭包(Closure) : 也叫Lambda表达式或匿名函数。

不像普通函数,闭包可以对参数和返回类型进行推断,大多数时候都不需要写出来。以下定义都是合法的:

|| 42;
|x| x + 1;
|x:i32| x + 1;
|x:i32| -> i32 { x + 1 };

在上面的例子中,如果是单行语句且没有标注返回类型的时候,花括号是可选的。

  • 闭包可以像任何其他对象一样绑定到某个变量,然后可以像调用函数一样调用闭包
let f = |x| x + 1;
println!("x is {}", f(5))

打印结果如下:

x is 6

也可以在定义的地方直接调用:

let r = (|x| x + 1)(2); // r == 3
  • 闭包可以捕获外部的环境变量(自由变量)。

闭包捕获变量的方式分为三类:引用(&T)、可变引用(&mut T)和值(T)。捕获变量时,闭包会根据上面列出的顺序(从约束最少到约束最多),优先按引用捕获,必要时才会使用后面的捕获方式:

let x = 10;
// 闭包按引用捕获变量x,因为println!只需要引用参数
let show_x = || println!("x = {}", x);
show_x();

外部变量的引用保存在show_x对象中,对外部变量的借用持续到show_x离开作用域为止。

下面是一个捕获可变引用的例子:

let mut count = 0;
// 闭包按可变引用捕获变量count 
// incr也必须是可变的,因为它持有可变引用,调用incr会改变闭包的状态
let mut incr = || { count += 1; println!("count = {}", count); };
incr();

下面的代码演示了闭包转移捕获变量所有权时的情况(捕获变量的值):

use std::mem;

// b是不可复制类型,因此按值捕获时所有权会转移
let b = Box::new(12);
let f = || {
    println!("b = {}", b);
    // drop函数取T类型,因此闭包会按值捕获变量b
    mem::drop(b);
};
f();

调用闭包后b的所有权已经转移,无法再访问:

// 编译错误
println!("b = {}", b);

同样,因为b的所有权已经转移,无法再次调用这个闭包:

// 编译错误
f();

如果要强制按值捕获,可以在闭包前添加关键字move:

let f = move || {
    println!("b = {}", b);
};
f();

同样地,调用闭包后b的所有权已经转移,无法再访问。


文章作者: 李文洋
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 李文洋 !
评论
 上一篇
Android-RecycleView内部item点击事件 Android-RecycleView内部item点击事件
RecyclerView的使用——Item内部控件的点击事件一、在adapter中写item点击事件的接口供外部的activity使用/** * item内部的监听接口 */ public interface ItemInnerOncli
2020-10-21
下一篇 
IDEA 破解 IDEA 破解
2020-09-024 亲测有效:IntelliJ IDEA 2020.2 最新全家桶系列产品激活破解方法, JetBrains 全家桶激活激活方法1、下载最新版的idea 正常安装2、选择免费试用30天 3、进入到idea中后 将压缩包拖
2020-10-21
  目录