FnOnce , FnMut <RUST>
FnOnce
1 #[lang = "fn_once"]
2 #[must_use = "closures are lazy and do nothing unless called"]
3 pub trait FnOnce<Args> {
4 type Output;
5 extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
6 }
The version of the call operator that takes a by-value receiver.
Instance of FnOnce can be called, but might not be callable multiple times. Because of this, if the only thing known about a type is that it implements FnOnce, it can only be called once.
FnOnce is implemented automatically by closure that might consumer captured variable, as well as all types that implement FnMut, e.g(safe)function pointer (since FnOnce is a supertrait of FnMut).
Since both Fn and FnMut are subtraits of FnOnce, any instance of Fn or FnMut can be used where a FnOnce is expected.
Use FnOnce as a bound when you want to accept a parameter of function-like type and only need to call it once. If you need to call the parameter repeatedly, use FnMut as a bound; if you also need it to not mutate state, use Fn.
Aslo of note is the sapcial syntax for Fn traits(e.g Fn(usize, bool) -> usize). Those interested in the technical details of this can refer to the relevant section in the Rustonmicon.
1 fn consume_with_relish<F>(func: F)
2 where F: FnOnce() -> String
3 {
4 // 'func' consumers it captured variables, so it cannot be run more than once.
5 println!("Consumed: {}", func());
6
7 println!("Delicious!");
8
9 //Attempting to invoke 'func()' again will therow a 'use of moved
10 // value 'error for 'func'
11 }
12
13 let x = String::from("x");
14 let consume_and_return_x = move || x;
15 consume_with_relish(consume_and_return_x);
FnMut
1 Trait std::ops::FnMut
2
3 #[lang = "fn_mut"]
4 #[must_use = "clousure are lazy and do nothing unless called"]
5 pub trait FnMut<Args>: FnOnce<Args> {
6 extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
7 }
The version of the call operator that takes a mutale receiver.
Instance of FnMut can be called repeatedly and many mutate state.
FnMut is implemented automatically by closures which take mutable reeferences to captured variables, as well as all types that implement Fn, e.g, (safe) functuin pointer(since FnMut is a supertrait of Fn). Additionally, for any type F that implements FnMut, &mut F implements FnMut, too.
1 pub fn map<F, T, U>(values: Vec<T>, mut f: F) -> Vec<U>
2 where F: FnMut(T) -> U, {
3 let mut v = Vec::with_capacity(values.len());
4 for val in vlaues {
5 v.push(f(val));
6 }
7 v
8 }
9
10
11 fn square(x: i32) -> i32 {
12 x * x
13 }
14
15 #[test]
16 fn func_single() {
17 let input = vec![2];
18 let expected = vec![4];
19 assert_eq!(map(input, square), expected);
20 }
21
22 #[test]
23 #[ignore]
24 fn func_multi() {
25 let input = vec![2, 3, 4, 5];
26 let expected = vec![4,9,16,25];
27 assert_eq!(map(input, square),expected);
28 }
29
30 #[test]
31 #[ignore]
32 fn closure() {
33 let input = vec![2, 3, 4, 5];
34 let expected = vec![4,9, 16, 25];
35 assert_eq!(map(input, |x| x*x), expected);
36 }
37
38 #[test]
39 #[ignore]
40 fn closure_floats() {
41 let input = vec![2.0, 3.0, 4.0, 5.0];
42 let expected = vec![4.0, 9.0, 16.0, 25.0];
43 assert_eq!(map(input, |x| x*x), expected);
44 }
45
46 #[test]
47 #[ignore]
48 fn strings() {
49 let input = vec!["1".to_stirng(), "2".into(), "3".into()];
50 let expected = vec!["11".to_string(), "22".into(), "33".into()];
51 assert_eq!(map(input, |s| s.repeat(2)), expected);
52 }
53
54
55 #[test]
56 #[ignore]
57 fn change_in_type() {
58 let input: Vec<&str> = vec!["1", "2", "3"];
59 let expected: Vec<String> = vec!["1".into(), "2".into(), "3".into()];
60 assert_eq!(map(input, |s| s.to_string()), expected);
61 }
62
63 #[test]
64 #[ignore]
65 fn mutaing_closure() {
66 let mut counter = 0;
67 let input = vec![-2, 3, 4, -5];
68 let expected = vec![2, 3, 4,5];
69 let result = map(input, |x:i64| {
70 counter += 1;
71 x.abs()
72 });
73 assert_eq!(result, expected);
74 assert_eq!(counter, 4);
75 }
76
77 #[test]
78 #[ignore]
79 fn minimal_bounds_on_input_and_output() {
80 // mut be able to accept arbitrary input and output types
81 struct Foo;
82 struct Bar;
83 map(vec![Foo], |_| Bar);
84 }
FnOnce , FnMut <RUST>的更多相关文章
- FnOnce,FnMut和Fn
继承结构 FnOnce FnMut: FnOnce Fn: FnMut FnOnce就是说会转移闭包捕获变量的所有权,在闭包前加上move关键字可以限定此闭包为FnOnce move关键字是强制让环境 ...
- 【译】理解Rust中的闭包
原文标题:Understanding Closures in Rust 原文链接:https://medium.com/swlh/understanding-closures-in-rust-21f2 ...
- 闭包类型(Fn,FnMut,FnOnce)和move关键字
move关键字是强制让环境变量的所有权转移到闭包中而不管是不是发生了所有权的转移 move关键字和匿名函数是否是FnOnce没有必然联系,之和匿名函数体有关 当匿名函数体里转移了环境变量的所有权的时候 ...
- Tokio,Rust异步编程实践之路
缘起 在许多编程语言里,我们都非常乐于去研究在这个语言中所使用的异步网络编程的框架,比如说Python的 Gevent.asyncio,Nginx 和 OpenResty,Go 等,今年年初我开始接触 ...
- rust 高级话题
目录 rust高级话题 前言 零大小类型ZST 动态大小类型DST 正确的安装方法 结构体 复制和移动 特征对象 引用.生命周期.所有权 生命周期 错误处理 交叉编译 智能指针 闭包 动态分派和静态分 ...
- rust语法
目录 rust语法 前言 一.数据类型 1.1 标量scalar 1.2 复合compound 1.3 切片slice 1.4 引用(借用)reference 1.5 智能指针smart pointe ...
- Rust基础笔记:闭包
语法 Closure看上去是这样的: let plus_one = |x: i32| x + 1; assert_eq!(2, plus_one(1)); 首先创建一个绑定plus_one,然后将它分 ...
- 【译】理解Rust中的Futures(二)
原文标题:Understanding Futures in Rust -- Part 2 原文链接:https://www.viget.com/articles/understanding-futur ...
- the rust book 的简单入门笔记
rust learning day 1 (2021/05/27) 学了常量,变量,数据类型,控制流,所有权 char 的宽度是4字节,一个 unicode 的宽度 控制流条件都不要括号 rust 中的 ...
- Writing A Threadpool in Rust
文 Akisann@CNblogs / zhaihj@Github 本篇文章同时发布在Github上:https://zhaihj.github.io/writing-a-threadpool-in- ...
随机推荐
- 从源码解析Go exec timeout 实现机制
1. 背景 环境:golang 1.9,drawn 测试使用golang exec 执行命令,并配置过期时间,测试脚本如下. 现象:执行脚本后,到超时时间后并为超时退出,反而阻塞住了 func Tes ...
- P/Invoke之C#调用动态链接库DLL
本编所涉及到的工具以及框架: 1.Visual Studio 2022 2..net 6.0 P/Invok是什么? P/Invoke全称为Platform Invoke(平台调用),其实际上就是一种 ...
- 关于在vue3中使用vuex与在vue2中使用vuex的区别
首先vue2中vuex版本是4.x以下,vue3中使用vuex需要保证vuex版本在4.x及以上. 以下说一说怎么在vue3中使用vuex,与vue2大同小异 首先在views新建一个store文件夹 ...
- 从头开始,手写android应用框架(一)
前言 搭建android项目框架前,我们需要先定义要框架的结构,因为android框架本身的结构就很复杂,如果一开始没定义好结构,那么后续的使用就会事倍功半. 结构如下: com.kiba.frame ...
- [Java]枚举类型:遍历为List
方式1 Demo import com.google.common.collect.Lists; import java.util.HashMap; import java.util.List; im ...
- Java Stream流
Java8 Stream流编程 Stream 使用一种类似于SQL语句从数据库查询数据的直观方式来提供对 Java 集合运算和表达的高阶抽象.得益于 Lambda 所带来的函数式编程,Stream A ...
- 我的第一个NPM包:panghu-planebattle-esm(胖虎飞机大战)使用说明
好家伙,我的包终于开发完啦 欢迎使用胖虎的飞机大战包!! 为你的主页添加色彩 这是一个有趣的网页小游戏包,使用canvas和js开发 使用ES6模块化开发 效果图如下: (觉得图片太sb的可以自己改 ...
- P4055 [JSOI2009] 游戏(博弈论 、最大匹配)
P4055 [JSOI2009] 游戏 目录 P4055 [JSOI2009] 游戏 题目传送门 题目大意 : 思路: code 题目传送门 题目大意 : 小AA和小YY玩游戏,在这个游戏中,同一个格 ...
- 使用 Semantic Kernel 实现 Microsoft 365 Copilot 分析
3月16日,微软发布了微软365 Copilot[1]. Microsoft 365 Copilot 将您现有的 Word.Excel.PowerPoint.Outlook 和 Teams 与大型语言 ...
- boot-admin整合Liquibase实现数据库版本管理
Liquibase 和 Flyway 是两款成熟的.优秀的.开源/商业版的数据库版本管理工具,鉴于 Flyway 的社区版本对 Oracle 数据库支持存在限制,所以 boot-admin 选择整合 ...