Rust学习(六):函数式编程

Rust学习(六):函数式编程

我们在前一篇博客中已经介绍了如何通过trait和impl实现Rust的面向对象编程,但是Rust本身实际上并不提倡通过类来解决问题。Rust推崇的是函数式编程,强调将函数作为参数值或者其他函数的返回值,将函数赋值给变量之后在继续执行。其中最重要的两个概念就是:闭包函数和迭代器。

1、闭包函数:

闭包函数是一种可以保存变量或作为参数传递给其他函数使用的匿名函数,和C++中的lambda表达式非常相似,闭包可以在一处创建,然后在不同的上下文中使用,同时闭包函数可以捕获调用者的作用域中的值:

//定义闭包函数:
|parameters| {cody_body;return_value
}

闭包函数还可以进一步简化,Rust可以自动推动闭包函数的参数类型和返回值类型,因此,闭包可以没有参数和返回值:

let is_even = |x| {x % 2 == 0
};let num = 10;
println!("{num} is even {}", is_even(num));

如上面这个案例所示:使用闭包可以只将其赋值给变量,然后就像调用函数一样调用它即可(doge),同时闭包也可以使用外部变量:

let val = 2;
let add_val = |x| {x + val};
let num = 2;
let res = add_val(num);
println!("{num} + {val} = {res}");

如果大家和记得前面对所有权的描述,,那就一定会好奇:这里的闭包函数获取的到底是外部变量的所有权还是外部变量的引用?Rust为此设计了三个trait:

  • FnOnce:使用这个trait的闭包函数会获取外部变量的所有权。
  • FnMut:获取外部变量的可变引用。
  • Fn:获取外部变量的借用值。

如果需要强制将外部变量所有权转移到闭包内,那么可以使用move关键字:

let val = 2;
let add_val = move |x| {x+val};

2、迭代器:

迭代器会把集合中所有元素按照顺序一个一个传递给处理逻辑,允许对一个序列进行某些处理,并且会遍历这个序列中的每一项以决定何时结束。我们之前使用的for循环就是一个迭代器,迭代器默认实现了Iterator trait——iter(),用于返回i迭代器和next(),用于返回迭代器的下一项,他们是迭代器的核心功能!

根据迭代器迭代时是否可以修改数据,iter()方法有三个版本:

  • iter():返回只读可重入迭代器,元素类型:&T
  • iter_mut():返回可修改可重入迭代器,元素类型:&mut T
  • into_iter():返回只读不可重入迭代器,元素类型:T

可重入是指:迭代后原始数据还能使用,不可重入则代表迭代器消费了原始数据(这里可以借用python中的pop()方法,取出元素,并删除)

let nums = vec![1, 2, 3, 4, 5, 6];//使用iter()方法:
for num in nums.iter() {println!("num:{num}");
}
println!("{:?}", nums);  //可以使用原数据nums//使用iter_mut()方法:
for num in nums.iter_mut() {*num += 1;
}
println!("{:?}", nums);  //可以使用原数据nums//使用into_iter()方法:
for num in nums.into_iter() {println!("num:{num}");
}
//for num in nums.iter() {println!("num:{num}");}  错误!nums已经被消费

消费是迭代器中的一种有趣且特殊的操作,sum, next, nth, fold等都是消费者,他们会对迭代器进行操作,得到最终值:

fn main() {let nums = vec![1, 2, 3, 4, 5, 6];let nums_iter = nums.iter();let total = nums_iter.sum::<i32>();let new_nums : Vec<i32> = (0..100).filter(|&n| n % 2 == 0).collect();println!("{:?}", new_nums);// 求小于等于1000的能被3或5整除的所有整数之和:let sum = (1..1000).filter(|n| n % 3 == 0 || n % 5 == 0).sum::<u32>();println!("{sum}");
}

实际上,除了函数式编程之外,还有命令式编程、声明式编程等多种编程范式。我们平时所用的面向对象编程(C++和python)和结构式编程(C)都属于命令式编程,命令式编程的主要思想是一步一步的精确的给出计算机运行程序的指令,而声明式编程(SQL)则以数据结构的形式表达变成逻辑,主要思想是告诉计算机应该做什么,而不是具体怎么做的(其实有点夸大了),函数式编程的思想和声明式编程类似,它更进一步是面向数学的抽象,旨在将计算描述为一种数学表达式求值,寻求一种输入输出的映射关系。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/61177.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为USG5500防火墙配置NAT

实验要求&#xff1a; 1.按照拓扑图部署网络环境&#xff0c;使用USG5500防火墙&#xff0c;将防火墙接口加入相应的区域&#xff0c;添加区域访问规则使内网trust区域可以访问DMZ区域的web服务器和untrust区域的web服务器。 2.在防火墙上配置easy-ip&#xff0c;使trust区域…

三角波生成函数

% 设置时间范围和采样频率 t 0:0.01:2; % 时间从0到2秒&#xff0c;步长为0.01秒% 定义频率 f 和角频率 theta f 5; % 频率为5Hz theta 2 * pi * f * t;% 初始化输出向量 y zeros(size(t));% 根据给定的公式计算 y for k 1:fy y (-1)^(k-1)*(2 /(k * pi)) * sin(k * the…

Lc70--319.两个数组的交集(二分查找)---Java版

1.题目描述 2.思路 用集合求交集&#xff0c;因为集合里面的元素要满足不重复、无序、唯一。使得集合在去重、查找和集合操作&#xff08;如交集、并集、差集等&#xff09;中非常高效和方便。 3.代码实现 class Solution {public int[] intersection(int[] nums1, int[] nu…

操作系统实验 C++实现生产者-消费者问题

实验目的 1、进一步加深理解进程同步的概念 2、加深对进程通信的理解 3、了解Linux下共享内存的使用方法 实验内容 1、按照下面要求&#xff0c;写两个c程序&#xff0c;分别是生产者producer.c以及customer.c 2、一组生产者和一组消费者进程共享一块环形缓冲区 使用共…

无人机在森林中的应用!

一、森林资源调查 无人机可以利用遥感技术快速获取所需区域高精度的空间遥感信息&#xff0c;对森林图斑进行精确区划。相较于传统手段&#xff0c;无人机调查具有低成本、高效率、高时效的特点&#xff0c;尤其在地理环境条件不好的区域&#xff0c;调查人员无法或难以到达的…

Android学生信息管理APP的设计与开发

1. 项目布局设计 页面1&#xff1a;学生信息添加页面 采用线性布局&#xff0c;页面中控件包含TextView、editView、Button等。 布局核心代码如下&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http…

AI(12)-飘带

1.【钢笔工具】画第一条曲线 2.【钢笔工具】画第二条曲线 3-全选两条曲线-【对象】-【混合】-【混合选项】-【指定的步数】-【15】 3-1-【对象】-【混合】-【建立】 4-双击打开【渐变工具】 4-1-【类型&#xff1a;线性】 4-2-点击切换【描边】在上方 4-3-关闭【填色】 4-4-点…

智能指针原理、使用和实现——C++11新特性(三)

目录 一、智能指针的理解 二、智能指针的类型 三、shared_ptr的原理 1.引用计数 2.循环引用问题 3.weak_ptr处理逻辑 四、shared_ptr的实现 五、定制删除器 六、源码 一、智能指针的理解 问题&#xff1a;什么是智能指针&#xff1f;为什么要有智能指针&#xff1f;智…

NIST 发布后量子密码学转型战略草案

美国国家标准与技术研究所 (NIST) 发布了其初步战略草案&#xff0c;即内部报告 (IR) 8547&#xff0c;标题为“向后量子密码标准过渡”。 该草案概述了 NIST 从当前易受量子计算攻击的加密算法迁移到抗量子替代算法的战略。该草案于 2024 年 11 月 12 日发布&#xff0c;开放…

使用uniapp开发微信小程序使用uni_modules导致主包文件过大,无法发布的解决方法

在使用uniapp开发微信小程序时候&#xff0c;过多的引入uni_modules的组件库&#xff0c;会导致主包文件过大&#xff0c;导致无法上传微信小程序&#xff0c;主包要求大小不超过1.5MB.分包大小每个不能超过2M。 解决方法&#xff1a;分包。 1.对每个除了主页面navbar的页面进…

WPF窗体基本知识-笔记-命名空间

窗体程序关闭方式 命名空间:可以理解命名空间的作用为引用下面的控件对象 给控件命名:一般都用x:Name,也可以用Name但是有的控件不支持 布局控件(容器)的类型 布局控件继承于Panel的控件,其中下面的border不是布局控件,panel是抽象类 在重叠的情况下,Zindex值越大的就在上面 Z…

【android USB 串口通信助手】stm32 源码demo 单片机与手机通信 Android studio 20241118

android 【OTG线】 接 下位机STM32【USB】 通过百度网盘分享的文件&#xff1a;USBToSerialPort.apk 链接&#xff1a;https://pan.baidu.com/s/122McdmBDUxEtYiEKFunFUg?pwd8888 提取码&#xff1a;8888 android 【OTG线】 接 【USB转TTL】 接 【串口(下位机 SMT32等)】 需…

SpringBoot源码解析(四):解析应用参数args

SpringBoot源码系列文章 SpringBoot源码解析(一)&#xff1a;SpringApplication构造方法 SpringBoot源码解析(二)&#xff1a;引导上下文DefaultBootstrapContext SpringBoot源码解析(三)&#xff1a;启动开始阶段 SpringBoot源码解析(四)&#xff1a;解析应用参数args 目录…

使用IDEA+Maven实现MapReduced的WordCount

使用IDEAMaven实现MapReduce 准备工作 在桌面创建文件wordfile1.txt I love Spark I love Hadoop在桌面创建文件wordfile2.txt Hadoop is good Spark is fast上传文件到Hadoop # 启动Hadoop cd /usr/local/hadoop ./sbin/start-dfs.sh # 删除HDFS的hadoop对应的input和out…

Spring Cloud Ribbon 实现“负载均衡”的详细配置说明

1. Ribbon 介绍 Ribbon 是什么 &#xff1f; 1.Spring Cloud Ribbon 是基于Netflix Ribbon 实现的一套客户端&#xff0c;负载均衡的工具 2.Ribbon 主要功能是提供客户端负载均衡算法和服务调用 3.Ribbon 客户端组件提供一系列完善的配置项如“连接超时&#xff0c;重试” 4…

TSMC12nm工艺数字IC后端实现难点都有哪些?

大家知道咱们社区近期TSMC 12nm ARM Cortexa-A72(1P9M 6Track Metal Stack)即将开班。这里小编要强调一点:不要认为跑了先进工艺的项目就会很有竞争力&#xff01;如果你仅仅是跑个先进工艺的flow&#xff0c;不懂先进工艺在数字IC后端实现上的不同点&#xff0c;为何有这样的不…

使用微信小程序调用飞桨PaddleX平台自行训练的模型——微信小程序用训练的牡丹花模型Demo测试

&#x1f3bc;个人主页&#xff1a;【Y小夜】 &#x1f60e;作者简介&#xff1a;一位双非学校的大二学生&#xff0c;编程爱好者&#xff0c; 专注于基础和实战分享&#xff0c;欢迎私信咨询&#xff01; &#x1f386;入门专栏&#xff1a;&#x1f387;【MySQL&#xff0…

【C++】基础篇二、引用详解

文章目录 1.引用的概念和定义2.引用的特性3.引用的使用3.1 做函数返回值3.2 传参 3.3 其他使用 4.const的运用引用的权限问题&#xff1b;const修饰引用&#xff1b; 5.指针和引用的对比 1.引用的概念和定义 在介绍概念之前先说一下引用的符号——“ & ”&#xff1b;对于这…

D3基础:绘制圆形、椭圆形、多边形、线、路径、矩形

在D3.js中&#xff0c;可以通过SVG元素来创建各种几何图形。以下是D3.js中常用的几何图形及其简单的创建方法&#xff1a; 1. 圆形 (Circle) 圆形是最基本的形状之一&#xff0c;可以通过<circle>标签来创建。 <!DOCTYPE html> <html> <head><met…

前端监控之sourcemap精准定位和还原错误源码

一、概述 在前端开发中&#xff0c;监控和错误追踪是确保应用稳定性和用户体验的重要环节。 随着前端应用的复杂性增加&#xff0c;JavaScript错误监控变得尤为重要。在生产环境中&#xff0c;为了优化加载速度和性能&#xff0c;前端代码通常会被压缩和混淆。这虽然提升了性…