闭包只有这三种模式,即
Fn:它只能从闭包环境中不可变借用相关变量;
FnMut:它能可变借用捕获的变量,并改变闭包环境;
FnOnce:它捕获的闭包环境变量,闭包本身只能用一次,不是说闭包中的变量被一次性消费,而是指闭包本身;

为什么会引出Fn,FnMut,FnOnce?

一、Fn、FnMut和FnMut
1、Fn
看一下以下的例子:


fn call_Fn(x: i32, f: impl Fn(i32) -> i32) {f(x);
}
fn main() {let j = 5;let g = |i: i32| i + j;call_Fn(2, g);thread::sleep_ms(500000);
}

为什么用Fn,而不是其它?FnMut? FnOnce?

    let f_0 = |i: i32| i+ j;

在闭包g中,输入参数是i32,返回参数为i32,环境变量为j,在这个过程中,环境变量并没有改变。因此,用Fn是合适的; 用FnMut是不合适的。

2、FnMut

我把上面的例子改一下:

fn call_FnMut(x: i32, mut f: impl FnMut(i32) -> ()) {f(x);
}
fn main() {let mut j = 5;let g = |i: i32| j = i + j;call_Fn(2, g);//call_Fn(2, g); //error,只能调用一次thread::sleep_ms(500000);
}

同样,

    let f_0 = |i: i32| j = i + j;

输入参数为i,i32; 环境变量j,j为mut类型。这个闭包改变了j。
因此,适合的就是FnMut,不适用用Fn。但改成FnOnce也是可以的,即:

fn call_FnOnce(x: i32, mut f: impl FnOnce(i32) -> ()) {f(x);
}

3、FnOnce

fn call<F:FnOnce()>(f:F){f()
}
fn main() {let mut v = vec![];let g = ||{v.push(1);println!("v:{:?}",v);v};//call(g);//call(g); 只能调用一次,不能调用第二次g();}

如果call中换成Fn或FnMut,都是不行的 。g()或call()只能调用一次;

二、共同适用的情况

有意思的是,上面FnOnce 的例子,其实也可以用Fn;

fn call_Fn(mut f: impl Fn() -> ()) -> () {f();
}fn main() {let sy_time0 = SystemTime::now();let s =  "i love rust!";let g = || println!("{}", s);call_Fn(g);thread::sleep_ms(500000);
}

包括,加一行代码,Fn与FnMut都适合。

fn call_FnOnce(i: usize, mut f: impl FnOnce(usize) -> ()) -> () {f(i);
}fn main() {let sy_time0 = SystemTime::now();let s = "abc";let g = |i: usize| {println!("{}", s);s.repeat(i); };call_FnOnce(2, g);thread::sleep_ms(500000);
}

还有:

fn call_FnOnce(mut f: impl FnOnce() -> ()) -> () {f();
}fn main() {let s = "i love rust!";let g = || {let ss ="hello".to_string() + s;println!("{:?}", ss);};call_FnOnce(g);call_FnOnce(g);println!("s:{:?}",s);call_FnOnce(g);g();g();thread::sleep_ms(500000);
}

同样,

此时适合用FnOnce,也适合用Fn; 即:

fn call_Fn(mut f: impl Fn() -> ()) -> () {f();
}

三、闭包中参数可变时

fn call_Fn(x: i32, f: impl Fn(i32) -> ()) -> () {f(x);
}fn main() {let sy_time0 = SystemTime::now();let j = 5;let g = |i: i32| i = i + j;  // i需要如何改变,才能通过?call_Fn(2, g);thread::sleep_ms(500000);
}

为什么上面的代码是不行?

    let g = |i: i32| i = i + j;

从闭包来看,闭包的参数已经发生变化,因此需要改成以下模式:

    let g = |mut i: i32| i = i + j;

就可以了。

上面的也可以写成FnMut的形式:

fn call_FnMut(x: i32, mut f: impl FnMut(i32) -> ()) -> () {f(x);
}fn main() {let sy_time0 = SystemTime::now();let j = 5;let mut g = |mut i: i32| i = i + j;call_FnMut(2, g);thread::sleep_ms(500000);
}

Rust:Fn,FnMut,FnOnce相关推荐

  1. Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。(python)

    Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1.当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少. 刚开始做 def svd(n):if(n ...

  2. 编写一个函数,计算两个数字的和,差,积,商

    1 编写一个函数,计算两个数字的和.差.积.商 要求:使用传参的形式 function demo(num1, num2) { console.log(num1 + num2); console.log ...

  3. 一文解决Rust字符串:String,str,String,str,CString,CStr

    一.str和&str和String的区别 1.存放位置,可变不可变: str来源于Rust本身的数据类型,而String类型来自于标准库.首先看一下str 和 String之间的区别:Stri ...

  4. 【rust语言】(1):开始学习rust语言,使用vscode进行开发,rust不要做为自己的第一门开发语言,c++和rust都要学习好,成年人两个都要。

    目录 前言 1,关于Rust学习,对比了一段时间还是决定学习了 2,官方网站 3,使用Cargo创建项目和进行包管理, 4,增加项目依赖包,和nodejs比较像 5,另外一个tauri app 框架, ...

  5. gm怎么刷东西 rust_Rust语言:解引用详述,搞不明白这个概念,趁早放弃Rust

    Rust是内存安全的,对新手来说,最大的困难是可恶的编译器,在其他语言上面叱咤风云,偏偏被Rust搞到崩溃.所以,大家都戏谑道,Rust是面向编译器编程. 和编译器做斗争的过程中,遇到最多的是,变量所 ...

  6. Draconian,自由或保姆状态:Java,C#,C,C ++,Go和Rust中的并发意识形态

    为什么我们需要并发 (Why we need Concurrency) Once, there was a good old time when clock speed doubled every 1 ...

  7. 分类评价指标:TP、TN、FP、FN、Recall,以及人脸识别评价指标TAR、FAR、FRR

    文章目录: 1 关于gallery和probe的介绍 2 二分类常用评价指标 2.1 二分类常用的评价指标 2.2 混淆矩阵 2.3 评价指标 3 人脸识别基本概念 3.1 人脸验证(Face Ver ...

  8. 蓝牙HID驱动:某键盘,Fn组合键,小概率无响应,普通Keyboard功能正常。

    蓝牙HID驱动:某键盘,Fn组合键,小概率无响应,普通Keyboard功能正常. 分析:同平台产品ABC,A搭配定制键盘,有该问题,B,C均无此问题. 初步判断为A搭配的键盘有问题.但看了HCI lo ...

  9. LWN:内核热点: folio,多代LRU,以及Rust!

    关注了就能看到更多这么棒的文章哦- The kernel radar: folios, multi-generational LRU, and Rust By Jonathan Corbet Janu ...

  10. rust2020几月上架ps4_《腐蚀Rust》将于上架PS4,老玩家:爆肝警告,入坑需谨慎

    作为多人对抗生存游戏,<腐蚀Rust>就属于非常符合"沉溺式"标准的游戏,在游戏中你可以尽情的体验零基础生存带来的乐趣.对抗自然,制作衣服道具武器等,这是一个由木棍进化 ...

最新文章

  1. php 代码规范 工具,PHP工具篇:PHPStorm IDE使用CodeSniffer代码规范化管理
  2. “东湖”的艄公--漫步绍兴(四)
  3. java文件头_对java文件头的解析
  4. share-Nothing原理
  5. 最近失业,不知道干什么好,随便乱写,无内容。
  6. Unity开发《一起来捉妖》教程 | 1.陀螺仪控制相机
  7. java 中的随机数
  8. dbeaver 视图有一个x_《工程制图》——视图、剖视图、断面图、局部放大图
  9. kswapd进程与swap、swappiness之间的关系及原理
  10. 【人脸识别】基于matlab ksvd字典学习人脸表情识别【含Matlab源码 460期】
  11. 路由器的硬件测试软件,路由器也跑分?路由器测试App路小胖体验
  12. FlashFXP用到的功能
  13. FastJson耗时
  14. gazebo可以另存为world
  15. ROC和DO的双重设计:打造出支付领域的重磅产品
  16. 服务器排性能行榜,服务器CPU性能排行榜天梯图(双路/三路/四路)
  17. linux 查看文件信息
  18. C_.NET+Framdwork题库(未整理完,有时间再补)
  19. opencv-python 读取视频时如何判断读取到最后一张
  20. 开发要不要做测试,怎么做?

热门文章

  1. 中国科学院图书馆分类法
  2. Maven - Maven3实战学习笔记(1)Maven使用入门
  3. MySQL-快速入门(15)MySQL Replication,主从复制
  4. day_4 Selenium请求库
  5. Eureka-Client(Golang实现)
  6. Java中String、StringBuffer、StringBuilder的区别详解
  7. xdc如何设置输入延时
  8. 《现代前端技术解析》第七章读书笔记
  9. 机器人操作系统——ROS,Robot Operating System
  10. The 7th Zhejiang Provincial Collegiate Programming Contest-Problem B:B - Somali Pirates