Rust 函数

Rust编写命令行解压工具 windows11虽然自带了unzip工具,但是使用起来还是很不舒服,于是决定自己一个解压的命令行程序 命令行解析的包使用clap 解压所用的库为zip 解压函数为 use std::path::Path; use std::fs; use std::option::Option::Some; use std::io; // zip_file是文件的路径,target是目标文件夹的路径 pub fn extra(zip_file: &Path, target: &Path) { . 阅读详情
函数

Rust支持函数式编程。

函数本身就是一种类型,函数类型变量可以作为其他函数的参数或者返回值,也可以赋值给别的变量,还可以直接调用执行。

定义函数

使用fn关键字定义函数,函数由函数签名和函数体组成。

函数签名由函数名、参数、返回值类型组成

函数体包含于{}内,是函数要执行的具体代码。

函数需要调用才会执行。

fn add(x: i32, y:i32) -> i32 {
    x+y   // 结尾没有分号
}

fn main() {
    let x = 5;
    let y = {
        let x = 2;
        x + 1  // 结尾没有分号
    };
    
    let sum = add(x,y);
    println!("{} + {} = {}",x,y,sum);
}
  • main函数

    main函数是程序的入口函数,对于可执行文件来说,main函数是必不可少的,对于库函数来说,main函数不是必须的

  • 函数体

    函数体由一系列语句和一个可选的结尾表达式构成。

    结尾没有分号,代表这是一个表达式而非语句,将会自动返回表达式的值,表示式的结尾如果加上分号,就变成了语句,语句没有返回值

  • 函数参数

    是函数签名的一部分。

    函数参数必须明确指定数据类型,但不能指定默认值。

    函数参数可以分为可变和不可变参数,默认不可变参数,需要可变操作时,需要加上mut关键字。

  • 返回值

    如果函数需要返回值给调用者,在函数定义时需要明确返回值类型。

    使用 -> 数据类型来定义

    函数只能有一个返回值,需要返回多个值时,可以使用元组类型

    Rust中每个函数都有返回值,即使没有显示返回值的函数,也会隐式地返回一个单元值()

    一般,函数隐式地返回函数体最后一个表达式的值

    可以使用return 语句来显示返回。

方法和函数

方法和函数类似,使用fn关键字定义,可以有参数、返回值和函数体。

结构体的方法必须在结构体的上下文中定义,也就是定义在impl块中。

在impl块中定义的不一定是方法,也有可能是关联函数。

方法要求第一个参数必须是self, 代表调用该方法的结构体实例。

在方法中使用&self能够读取实例中的数据,使用&mut self能够向实例中写入数据。

使用方法替代函数的最大好处在于组织性,将结构体实例的所有行为都一起放入impl块中

关联函数是指在impl块中定义,但是不以self作为参数的函数,与结构体相关联,但是不直接作用于结构体实例,常用作返回一个结构体实例的构造函数。

调用:

  • 在方法内部可以使用self.字段名 来访问结构体的字段
  • 在方法外使用实例名.方法名 调用方法
  • 调用关联函数使用 结构体名::关联函数名
  • 在调用结构体方法时,第一个参数self不需要传递实参,由Rust编译器完成
pub struct Student {
    name :&'static str,
    score : i32,
}

impl Student {
    pub fn new(name : &'static str,socre:i32) ->Self{
		Student{name,socre}
    }
    
    pub fn get_name(&self) -> &str {
		self.name
    }           
}

fn main(){
    let mut student : Student = Student::new("wkk",22);
    println!("{:?}",student);
}
高阶函数

以函数为参数或者返回值的函数。

函数是一种类型,函数类型的变量可以像其他类型的变量一样使用,可以被直接调用执行,也可以作为其他函数的参数或者返回值。

实现这一切的基础是函数指针,函数指针类型使用fn() 来指定

函数指针

指向函数的指针,值是函数的地址

声明中必须显示指定函数后指针的类型fn()

fn hello(){
    println!("hello wkk");
}

fn main(){
    let fn_ptr: fn() = hello;
    let other_fn = hello; // 函数hello本身的类型 , other_fn 不是函数指针类型
}

不管是函数指针类型,还是函数本身的类型,都可以直接进行调用。

函数作为参数

函数作为参数时,为了提升代码可读性,可以使用type关键字为函数指针类型定义别名

type MathOp = fn(i32,i32)->i32;
函数作为返回值

函数作为返回值时,也可以使用type关键字为函数指针类型定义别名

type MathOp = fn(i32,i32) -> i32;
fn math_op(op:&str) -> MathOp {
    match op {
        "add" => add,
         _    => subtract,
    }
}
闭包

闭包是在一个函数内创建的匿名函数,虽然没有函数名,但可以将闭包赋值给一个变量,通过调用该变量完成闭包的调用。

闭包可以访问外层函数中的变量,即闭包是一个可以捕获外部环境变量的函数。外部环境变量是指闭包定义时所在的作用域中的变量

基本语法

闭包由管道符 || 和 大括号 {} 组合而成

管道符中指定闭包的参数,如果由多个参数,使用逗号分隔。

闭包的参数类型可以省略。

管道符后可以指定返回值类型,但不是必须的。

大括号即闭包提,用来存放执行语句。如果闭包体只有一行,大括号可以省略。

闭包体中最后一个表达式的值默认为闭包的返回值。

let add_one = |x:u32| -> u32 { x+1 };
类型推断

闭包不像函数那样严格要求为参数和返回值注明类型,因为闭包通常是应用相对较小的场景和上下文,编译器可以可靠的推断参数和返回值的类型

fn add_one_v1 (x :u32) -> u32 {
    x+1
}

let add_one_v2 = |x:u32| -> u32 {
    x+1
};

let add_one_v3 = |x| { x+1 };

let add_one_v4 = |x| x+1;

虽然编译器会为每个参数和返回值推断出一个具体的类型,但是如果多次调用同一个闭包却传递不同类型的参数会导致类型错误。

第一次调用闭包时,传递的参数类型,会作为这个闭包的参数类型。

捕获环境变量

闭包和函数的最大区别是,闭包可以捕获和使用其被定义时所在的作用域中的变量。

let i = 1;
let add = |x| x+i;
// 闭包捕获和使用了作用域中的变量i的值
迭代器

使用过for循环来遍历数据集合,并对每个元素执行指定的操作,但这一过程必须使用一个变量记录数据集合中每一次访问的位置

迭代器模式是将遍历数据集合的行为抽象为单独的迭代对象,这样在遍历集合时可以把集合中所有元素按顺序传递给处理逻辑。使用迭代器可以极大地简化数据操作

iterator trait

Iterator trait是迭代器模式的抽象接口,接口中有两个重要方法。

  • iter 方法用于返回一个迭代器实例
  • next 方法用户返回迭代器的下一元素,并将其封装在Some函数中。如果已经迭代到了集合的末尾(最后一个元素的后面),返回None

通过迭代器将数组转换为迭代器,再调用迭代器的next方法获取元素。

注意,声明的变量iter必须是可变的, 因为每一次调用next方法都会从迭代器中消费一个元素

let v = [1,2,3];
let mut iter = v.iter();

println!("{:?}",iter.next());   // Some(1)
消费器

Rust中的迭代器都是惰性的,它们不会自动发生遍历行为。Iterator trait中定义了一类方法,这类方法叫作消费器。

通过消费器可以消费迭代器中的元素,这些方法的默认实现都调用了next方法。

常用的消费器sum, any,collect

其他消费器: std::iter::Iterator 中可以找到

  1. sum

    sum可以对迭代器中的元素执行求和操作,它将迭代器中每个元素进行累加并返回总和。

    let v = [1,2,4];
    let total : i32 = v.iter().sum();
    
  2. any

    查找迭代器中是否存在满足条件的元素

    let v = [1,2,3,4];
    let res1 = v.iter().any(|&x| x == 2);
    let res2 = v.iter().any(|x| *x == 2);
    

    消费器any的内部实现中,调用迭代器的next 方法返回Option<&[T]> 或 Option<&mut[T]> 类型的值,再通过模式匹配得到&[T] 或者 &mut[T] 类型值。

    在消费器any调用闭包中只有使用引用和解引用两种方式。

  3. collect

    collect可以将迭代器转换成指定的容器类型,即将迭代器中元素收集到指定的容器中。

    let v1 = [1,2,3];
    let v2:Vec<i32> = v1.iter().map(|x| x+1).collect();
    

    使用map方法对原迭代器中的每个元素调用闭包执行加1的操作并生成一个新的迭代器

迭代器适配器

适配器Iterator trait中定义了一类方法,这类方法叫作迭代器适配器

将当前迭代器转换成另一种类型的迭代器,并支持链式调用多个迭代器适配器

由于所有的迭代器都是惰性的,必须使用一个消费器来获取迭代器适配器的调用结果。

常用的迭代器适配器map, take,filter,rec 和zip

其他迭代器适配器可在std::iter中查找

  1. map

    适配器map对迭代器中每个元素调用闭包并生成一个新的迭代器。

    let v = [1,2,3];
    let result : Vec<i32> = v.iter()
    		.map(|x| x+3).collect();
    // 调用collect 方法将迭代器中的元素收集到动态数组中
    
  2. take

    take 生成一个仅迭代原迭代器中前n个元素的新迭代器,常用于遍历指定数量的场景。

    let v = [1,2,3];
    let res = v.iter().take(3);
    
  3. filter

    适配器filter 对迭代器中每个元素调用闭包并生成一个过滤元素的新迭代器。

    闭包会返回true或者false ,如果返回true则该元素放入新的迭代器,否则将该元素忽略。

    let v = [1,2,3];
    let result : Vec<i32> = v.iter()
    	.map(|x| x+3 )
    	.filter(|x| x%3 == 0)
    	.collect();
    
  4. rev

    通常迭代器从左到右进行迭代。

    适配器rev可以反转迭代方法,生成一个方向相反的新迭代器,即新的迭代方向将从右向左进行迭代。

    let v = [1,2,3];
    let res = v.iter().rev();
    
  5. zip

    适配器zip可以将两个迭代器压缩在一起生成一个新的迭代器。

    它在两个迭代器上同时迭代并返回一个元组,第一个元素来自第一个迭代器,第二个元素来自第二个迭代器。

    如果两个迭代器中任一个迭代器返回None, 适配器zip返回None

    let v1 = [1,2,3];
    let v2 = [2,3,5];
    let result:Vec<i32> = v1.iter().zip(v2.iter())
    	.map(|(a,b)| a+b)
    	.filter(|x| x%3 == 0)
    	.collect();
    
Rust语言的函数实现 在Rust中,函数的定义使用fn关键字。rustfn 函数名(参数1: 类型1, 参数2: 类型2) -> 返回类型 {// 函数体rusta + b在这个例子中,我们定义了一个名为add的函数,它接受两个i32类型的参数并返回它们的和,返回类型也是i32。Rust的函数实现是理解和使用这门语言的基础。通过函数的定义、参数、返回值以及闭包的应用,开发者可以实现复杂的逻辑并确保代码的可读性和可维护性。Rust独特的所有权和借用机制为函数操作提供了内存安全的保证,减少了潜在的内存错误。 阅读详情

相关推荐

Index-TTS-1.5:多模态语音合成的技术演进与商业落地实践

本文深入探讨了Index-TTS-1.5在多模态语音合成领域的技术演进与商业落地。该模型基于GPT风格的自回归Transformer架构,通过优化条件编码器和引入字符-拼音混合建模,显著提升了语音生成的稳定性、精准度和真实感,实现了高质量的零样本语音克隆。文章还详细介绍了其云端体验、本地WebUI部署及ComfyUI集成等实战路径,并分析了其在虚拟数字人、个性化内容创作等商业场景中的应用潜力与挑战。

weixin_29098367的博客 400

Rust学习笔记(9)——Option的几个方法及所有权问题

在rust的设计中,Option的设计非常巧妙,避免了其它语言中常见的Null引起的各种错误和异常。但Option与所有权的结合,尤其是在一些特定的数据结构,如链表、图等设计中,加上引用的各种约束,就使得Option的使用变得复杂起来。 1、unwrap方法 在确认Option不为None的情况下,可以用unwrap方法拆解出其中的值,并获取值的所有权。这里要强调的是,unwrap会消费Option本身的值,后面就不能再用了。 let a = Some(Box::new(5)); l

Konquerx的博客 9250

PySpark机器学习生产化陷阱:跨节点依赖问题的7种解决方案

隐式依赖陷阱使用ldd解决方案:在基础镜像中预装和路径冲突终极解法依赖树瘦身技巧用conda-tree可减少40%环境体积PySpark机器学习生产化的核心矛盾在于分布式环境的确定性与灵活性不可兼得。轻量级方案(1-3)牺牲一致性换取灵活性重量级方案(4-6)牺牲灵活性换取确定性混合方案(7)针对特殊场景补充正如某AI平台架构师所言:“环境一致性不是技术问题,而是工程纪律问题选择适合团队当前阶段的方案,建立严格的依赖管理流程,才能让PySpark真正扛起生产环境的大旗。

datacanvas2426的博客 909

Rust权威指南之函数式编程

本文来源于阅读《Rust权威指南》第十三章:函数式语言特征之闭包和迭代器的读书笔记。快速了解Rust中关于函数式编程的闭包和迭代器相关知识。

学习和工作总结,共勉! 1651

自动驾驶轨迹规划算法——Apollo EM Planner

Apollo EM Planner 是百度自动驾驶系统中的轨迹规划算法,采用期望-最大化(EM)迭代优化思想。其核心是将轨迹规划分解为路径优化(E-Step)和速度优化(M-Step)两个子问题,在Frenet坐标系下交替求解。算法先通过动态规划(DP)搜索粗路径,再使用二次规划(QP)进行平滑优化,并结合障碍物信息生成安全走廊。相较Lattice、Hybrid A*等规划器,EM Planner具有更好的实时性、动态障碍物处理能力和轨迹平滑性,适用于城市道路、高速公路等复杂场景。该算法通过解耦路径与速度优

swaggytiger的博客 2665

(八)DDR_PHY架构及功能——(PUB组成、初始化及Training流程、Clock关系)

文章目录一、DDR_PHY结构组成1.1、DDR Memory子系统1.2、DDR_PHY架构组成1.3、PUB模块功能实现流程1.3.1、DDR系统初始化流程1.3.2、PLL初始化流程 一、DDR_PHY结构组成 1.1、DDR Memory子系统   Memory子系统主要由DDR Controller和DDR_PHY(含DDR_IO)两个部分组成。DDR Controller主要承担其它子系统(如CPU)与Memory子系统进行数据交互时的传输效率及调度,DDR_PHY主要负责数据交互过程中的传输速

Mr.翟的博客 1万+

Rust踩雷笔记(5)——刷点链表的题(涉及智能指针Box,持续更新)

rust链表+智能指针的刷题记录,持续更新

umbrellalalalala的博客 1694

Qt + windows + Linux+QtInstallerFramework打包教程

本文介绍了使用Qt Installer Framework在Windows和Linux系统下打包Qt应用程序的完整教程。Windows部分详细说明了从下载安装框架、配置环境变量、生成release版本,到创建安装包目录结构和修改配置文件的完整流程。Linux部分则重点讲解了环境变量设置、桌面应用配置(.desktop文件)以及两种打包方案:一种使用linuxdeployqt生成AppImage文件,另一种采用类似Windows的安装包方式。教程提供了关键配置文件(config.xml、package.xml

Qt历险记,专注Qt技术,三年医疗设备研发经验,1年机器视觉研发经验,半年柔性传感研发经验。 516

Rust中的关键字Some、Option

根据Rust本身的设计哲学, 建议在设计某个变量时, 如果预计该变量某时刻可能会是空值(null/None)的话, 那么尽量用Option/Result来包裹它, 反过来说, 只有你可以肯定该变量不可能为空值时, 才无须这么搞。

西京刀客 9852

Cilium动手实验室: 精通之旅---1.Getting Started with Cilium

我们需要在 HTTP 层的第 7 层实施策略,以限制允许 tiefighter 调用的确切 API,以及不允许调用哪些 API。上仅需要的 API 资源的访问,从而为微服务之间的通信实施“最低权限”安全方法。船只上进行匹配,因此我们需要在该标签上进行匹配,此外,我们必须确保来自带有标签。为了模拟我们的连接测试,我们将使用 curl 执行简单的 API 调用。在我们立即开始更改策略之前,让我们考虑一下相应的网络策略应该是什么样子。的规则,该规则将通过 L3-L4 策略对死星的访问限制为仅帝国船只。

Q先生 1124

信号完整性之串扰

1.前言 串扰(Crosstalk)是指信号线之间由互感、互容而引起的耦合,由于这种耦合的存在,当某一信号线发生电平翻转时,在附近的信号线上将感应到一定程度的噪声。 2. 电路设计中抑制串扰的方法 2.1 控制高速信号线之间的间距和平行走线的长度 多个高速信号长距离平行走线时,其间距应遵循3W原则,如下图所示: 3W原则指两相邻信号线的中心间距不少于信号线宽度的3倍,当满足3W原则时,信号线之间...

sinat_15677011的博客 1万+

Rust 函数使用详解

函数签名:定义函数名称、参数和返回值。函数参数:支持类型注解,确保类型安全。语句与表达式:语句执行操作,表达式返回值。函数返回值:通过最后一个表达式隐式返回,或使用return关键字显式返回。通过合理使用这些特性,可以编写出高效且易于维护的 Rust 代码。无论是小型工具还是大型系统,Rust 的函数都能满足多样化的需求。

美味小鱼的杂货铺 1176

十一、增强现实

那都是n年前的老版本了,新版本完全没有这个问题,我就是纠结这个问题,搭建若干环境,又是vmware虚拟机,又是msys2,又是anaconda,又是找机器,折腾了几天,结果通通不是。以一张实际卡片为锚点,通过笔记本的摄像头,在显示器上将一个计算机内的3d物体显示在卡片上,类似于电影上看到的那种全息投影技术;如果你是想在windows环境下开发linux运行程序,那么CygWin/gcc是你的不二之选。而如果你想开发的是windows运行程序,并且追求速度,那么二者相比而言,MinGW是更好的选择。

3188

Rust编程的函数

然后,我们定义了一个名为calculate的函数,它接收一个函数参数op,类型为fn(i32, i32) -> i32,表示接收两个i32类型的参数并返回i32类型结果。函数可以返回一个值,返回值是函数的输出结果,用于提供函数执行后的结果或计算的值。函数可以接收参数,参数是函数的输入数据,用于在函数体中进行处理和操作。在上述示例中,我们定义了一个名为add的函数,它接收两个参数a和b,类型均为i32。在上述示例中,我们定义了一个名为greet的函数,它接收一个类型为&str的参数name。

夏天又到了的专栏 1194

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

rust 案例_Rust 函数

Rust 函数函数在 Rust 语言中是普遍存在的。通过之前的章节已经可以了解到 Rust 函数的基本形式:fn ( ) 其中 Rust 函数名称的命名风格是小写字母以下划线分割:实例fn main() {println!("Hello, world!");another_function();}fn another_function() {println!("Hello, runoob!")...

weixin_33431252的博客 148

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

上一篇: FPGA流水灯
下一篇: FPGA时钟IP核
暴风雨中的白杨
博客等级 码龄6年 1070粉丝 162原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暴风雨中的白杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值