Rust:Fn,FnMut,FnOnce
闭包只有这三种模式,即
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相关推荐
- 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 ...
- 编写一个函数,计算两个数字的和,差,积,商
1 编写一个函数,计算两个数字的和.差.积.商 要求:使用传参的形式 function demo(num1, num2) { console.log(num1 + num2); console.log ...
- 一文解决Rust字符串:String,str,String,str,CString,CStr
一.str和&str和String的区别 1.存放位置,可变不可变: str来源于Rust本身的数据类型,而String类型来自于标准库.首先看一下str 和 String之间的区别:Stri ...
- 【rust语言】(1):开始学习rust语言,使用vscode进行开发,rust不要做为自己的第一门开发语言,c++和rust都要学习好,成年人两个都要。
目录 前言 1,关于Rust学习,对比了一段时间还是决定学习了 2,官方网站 3,使用Cargo创建项目和进行包管理, 4,增加项目依赖包,和nodejs比较像 5,另外一个tauri app 框架, ...
- gm怎么刷东西 rust_Rust语言:解引用详述,搞不明白这个概念,趁早放弃Rust
Rust是内存安全的,对新手来说,最大的困难是可恶的编译器,在其他语言上面叱咤风云,偏偏被Rust搞到崩溃.所以,大家都戏谑道,Rust是面向编译器编程. 和编译器做斗争的过程中,遇到最多的是,变量所 ...
- Draconian,自由或保姆状态:Java,C#,C,C ++,Go和Rust中的并发意识形态
为什么我们需要并发 (Why we need Concurrency) Once, there was a good old time when clock speed doubled every 1 ...
- 分类评价指标:TP、TN、FP、FN、Recall,以及人脸识别评价指标TAR、FAR、FRR
文章目录: 1 关于gallery和probe的介绍 2 二分类常用评价指标 2.1 二分类常用的评价指标 2.2 混淆矩阵 2.3 评价指标 3 人脸识别基本概念 3.1 人脸验证(Face Ver ...
- 蓝牙HID驱动:某键盘,Fn组合键,小概率无响应,普通Keyboard功能正常。
蓝牙HID驱动:某键盘,Fn组合键,小概率无响应,普通Keyboard功能正常. 分析:同平台产品ABC,A搭配定制键盘,有该问题,B,C均无此问题. 初步判断为A搭配的键盘有问题.但看了HCI lo ...
- LWN:内核热点: folio,多代LRU,以及Rust!
关注了就能看到更多这么棒的文章哦- The kernel radar: folios, multi-generational LRU, and Rust By Jonathan Corbet Janu ...
- rust2020几月上架ps4_《腐蚀Rust》将于上架PS4,老玩家:爆肝警告,入坑需谨慎
作为多人对抗生存游戏,<腐蚀Rust>就属于非常符合"沉溺式"标准的游戏,在游戏中你可以尽情的体验零基础生存带来的乐趣.对抗自然,制作衣服道具武器等,这是一个由木棍进化 ...
最新文章
- php 代码规范 工具,PHP工具篇:PHPStorm IDE使用CodeSniffer代码规范化管理
- “东湖”的艄公--漫步绍兴(四)
- java文件头_对java文件头的解析
- share-Nothing原理
- 最近失业,不知道干什么好,随便乱写,无内容。
- Unity开发《一起来捉妖》教程 | 1.陀螺仪控制相机
- java 中的随机数
- dbeaver 视图有一个x_《工程制图》——视图、剖视图、断面图、局部放大图
- kswapd进程与swap、swappiness之间的关系及原理
- 【人脸识别】基于matlab ksvd字典学习人脸表情识别【含Matlab源码 460期】
- 路由器的硬件测试软件,路由器也跑分?路由器测试App路小胖体验
- FlashFXP用到的功能
- FastJson耗时
- gazebo可以另存为world
- ROC和DO的双重设计:打造出支付领域的重磅产品
- 服务器排性能行榜,服务器CPU性能排行榜天梯图(双路/三路/四路)
- linux 查看文件信息
- C_.NET+Framdwork题库(未整理完,有时间再补)
- opencv-python 读取视频时如何判断读取到最后一张
- 开发要不要做测试,怎么做?
热门文章
- 中国科学院图书馆分类法
- Maven - Maven3实战学习笔记(1)Maven使用入门
- MySQL-快速入门(15)MySQL Replication,主从复制
- day_4 Selenium请求库
- Eureka-Client(Golang实现)
- Java中String、StringBuffer、StringBuilder的区别详解
- xdc如何设置输入延时
- 《现代前端技术解析》第七章读书笔记
- 机器人操作系统——ROS,Robot Operating System
- The 7th Zhejiang Provincial Collegiate Programming Contest-Problem B:B - Somali Pirates