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- ...
随机推荐
- 百度360搜索关键词提交.py(亲测有效)
import requests keyword = "Python" try: kv = {'wd':keyword} # 百度 kv1 = {'q':keyword} # 360 ...
- springsecurity-jwt整合
2 springsecurity-jwt整合 欢迎关注博主公众号「Java大师」, 专注于分享Java领域干货文章http://www.javaman.cn/sb2/jwt 2.1整合springse ...
- Rancher(V2.6.3)安装K8s教程
Rancher(V2.6.3)安装K8s教程 一,安装前环境准备: 1,升级Linux服务器内核 Ubuntu20.04: #查看当前内核版本 uname -rs #查看软件库中可下载的内核 sudo ...
- (数据科学学习手札151)速通pandas2.0新版本干货内容
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,前两天pandas正式发布了其 ...
- golang pprof 监控系列(4) —— goroutine thread 统计原理
golang pprof 监控系列(4) -- goroutine thread 统计原理 大家好,我是蓝胖子. 在之前 golang pprof监控 系列文章里我分别介绍了go trace以及go ...
- pandas之字符串操作
Pandas 提供了一系列的字符串函数,因此能够很方便地对字符串进行处理.在本节,我们使用 Series 对象对常用的字符串函数进行讲解.常用的字符串处理函数如下表所示: 函数名称 函数功能和描述 l ...
- 五月二号java基础知识
1.使用Runnable接口可以轻松实现多个线程共享相同数据,只要用用一个可运行对象作为参数创建多个线程就可以了2.当一个线程对共享的数据进行操作时,应使之成为一个"原子操作"即在 ...
- day93:flask:Cookie&Session&请求钩子&捕获错误&上下文&Flask-Script
目录 1.HTTP的会话控制 2.Cookie 3.Session 4.请求钩子 5.捕获错误 6.上下文:context 7.Flask-Script 1.HTTP的会话控制 1.什么是会话控制? ...
- opencv基础
Python 和 OpenCV 的结合是计算机视觉领域中应用最为广泛的一种方式,它们的结合使得开发者可以快速.高效地完成各种视觉任务.本文将介绍 Python 和 OpenCV 的基础使用,包括安装. ...
- .NET敏捷开发框架-RDIFramework.NET V5.1发布(跨平台)
RDIFramework.NET,基于全新.NET Framework与.NET Core的快速信息化系统敏捷开发.整合框架,给用户和开发者最佳的.Net框架部署方案.为企业快速构建跨平台.企业级的应 ...