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>的更多相关文章

  1. FnOnce,FnMut和Fn

    继承结构 FnOnce FnMut: FnOnce Fn: FnMut FnOnce就是说会转移闭包捕获变量的所有权,在闭包前加上move关键字可以限定此闭包为FnOnce move关键字是强制让环境 ...

  2. 【译】理解Rust中的闭包

    原文标题:Understanding Closures in Rust 原文链接:https://medium.com/swlh/understanding-closures-in-rust-21f2 ...

  3. 闭包类型(Fn,FnMut,FnOnce)和move关键字

    move关键字是强制让环境变量的所有权转移到闭包中而不管是不是发生了所有权的转移 move关键字和匿名函数是否是FnOnce没有必然联系,之和匿名函数体有关 当匿名函数体里转移了环境变量的所有权的时候 ...

  4. Tokio,Rust异步编程实践之路

    缘起 在许多编程语言里,我们都非常乐于去研究在这个语言中所使用的异步网络编程的框架,比如说Python的 Gevent.asyncio,Nginx 和 OpenResty,Go 等,今年年初我开始接触 ...

  5. rust 高级话题

    目录 rust高级话题 前言 零大小类型ZST 动态大小类型DST 正确的安装方法 结构体 复制和移动 特征对象 引用.生命周期.所有权 生命周期 错误处理 交叉编译 智能指针 闭包 动态分派和静态分 ...

  6. rust语法

    目录 rust语法 前言 一.数据类型 1.1 标量scalar 1.2 复合compound 1.3 切片slice 1.4 引用(借用)reference 1.5 智能指针smart pointe ...

  7. Rust基础笔记:闭包

    语法 Closure看上去是这样的: let plus_one = |x: i32| x + 1; assert_eq!(2, plus_one(1)); 首先创建一个绑定plus_one,然后将它分 ...

  8. 【译】理解Rust中的Futures(二)

    原文标题:Understanding Futures in Rust -- Part 2 原文链接:https://www.viget.com/articles/understanding-futur ...

  9. the rust book 的简单入门笔记

    rust learning day 1 (2021/05/27) 学了常量,变量,数据类型,控制流,所有权 char 的宽度是4字节,一个 unicode 的宽度 控制流条件都不要括号 rust 中的 ...

  10. Writing A Threadpool in Rust

    文 Akisann@CNblogs / zhaihj@Github 本篇文章同时发布在Github上:https://zhaihj.github.io/writing-a-threadpool-in- ...

随机推荐

  1. 打工人都在用的AI工具(第二期)

    更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流. 上周更新的打工人都在用的AI工具(第一期)收到了小伙伴们的高度好评,于是很多小伙伴们急急忙忙的催更,技术 ...

  2. 安装KubeOperator并导入现有集群进行管理

    安装KubeOperator并导入现有集群进行管理 介绍 KubeOperator 是一个开源的轻量级 Kubernetes 发行版,专注于帮助企业规划.部署和运营生产级别的 Kubernetes 集 ...

  3. groovy, Scala和kotlin区别

    所谓Scala的目的是什么?事实上Scala作者Martin Odesky他在<Programming in Scala>中写到,Scala的目的是为了更好的融合OO与FP,确实,不是取代 ...

  4. [Linux/Redis]搭建Redis集群

    1 基本信息 3台服务器(CentOS7.3) 192.168.1.101 node101 192.168.1.102 node102 192.168.1.103 node103 2 单机 安装 Re ...

  5. Go For Web:一篇文章带你用 Go 搭建一个最简单的 Web 服务、了解 Golang 运行 web 的原理

    前言: 本文作为解决如何通过 Golang 来编写 Web 应用这个问题的前瞻,对 Golang 中的 Web 基础部分进行一个简单的介绍.目前 Go 拥有成熟的 Http 处理包,所以我们去编写一个 ...

  6. nginx配置phpcms v9伪静态规则 phpcms伪静态 404 Not Found

    location / { if (!-f $request_filename){ rewrite (.*) /index.php; } rewrite ^/caipu-([0-9]+)-([0-9]+ ...

  7. 开源后台管理系统解决方案 boot-admin 简介

    介绍 boot-admin 是一款采用前后端分离架构模式的后台管理框架.系统提炼自实际项目,兼具RuoYi-Vue前端分离版和Ruoyi-Cloud微服务版功能与技术特点. boot-admin 既有 ...

  8. Html 设置标题栏顶部固定

    如何设置标题栏一直置顶固定显示? 只需要给标题栏所在的容器,以下设置:   position: fixed;   top: 0px;   left: 0px;   width: 100%; 位置固定在 ...

  9. 聊一聊 GDB 调试程序时的几个实用命令

    一:背景 1. 讲故事 用惯了宇宙第一的 Visual Studio 再用其他的开发工具还是有一点不习惯,不习惯在于想用的命令或者面板找不到,总的来说还是各有千秋吧,今天我们来聊一下几个在调试中比较实 ...

  10. css知识点简记

    1.改变position: fixed; 定位基准元素的方式,父级以上元素的: ① tranform属性值不为none的元素 ② perspective值不为none的元素 ③ will-change ...