当前位置: 首页 > news >正文

Rust编程基础之函数和表达式

1.Rust函数

在之前的文章中,我们已经见到了一个函数:main函数, 它是很多程序的入口点。也见过 fn 关键字,它用来声明新函数。

Rust 代码中的函数和变量名使用 snake case 规范风格。在 snake case 中,所有字母都是小写并使用下划线分隔单词。这是一个包含函数定义示例的程序:

fn main() {println!("Hello, world!");
​another_function();
}
​
fn another_function() {println!("Another function.");
}

我们在 Rust 中通过输入 fn 后面跟着函数名和一对圆括号来定义函数。大括号告诉编译器哪里是函数体的开始和结尾。

可以使用函数名后跟圆括号来调用我们定义过的任意函数。因为程序中已定义 another_function 函数,所以可以在 main 函数中调用它。注意,源码中 another_function 定义在 main 函数 之后;也可以定义在之前。Rust 不关心函数定义所在的位置,只要函数被调用时出现在调用之处可见的作用域内就行。

将上面的代码编译执行, 会看到有以下输出:

main 函数中的代码会按顺序执行。首先,打印 “Hello, world!” 信息,然后调用 another_function 函数并打印它的信息。

2.函数参数

我们可以定义为拥有 参数parameters)的函数,参数是特殊变量,是函数签名的一部分。当函数拥有参数(形参)时,可以为这些参数提供具体的值(实参)。

another_function 中,增加了一个参数:

fn main() {another_function(5);
}
​
fn another_function(x: i32) {println!("The value of x is: {x}");
}

尝试运行程序,将会输出如下内容:

another_function 的声明中有一个命名为 x 的参数。x 的类型被指定为 i32。当我们将 5 传给 another_function 时,println! 宏会把 5 放在格式字符串中包含 x 的那对花括号的位置。

在函数签名中,必须 声明每个参数的类型。这是 Rust 设计中一个经过慎重考虑的决定:要求在函数定义中提供类型注解,意味着编译器再也不需要你在代码的其他地方注明类型来指出你的意图。而且,在知道函数需要什么类型后,编译器就能够给出更有用的错误消息。

当定义多个参数时,使用逗号分隔,像这样:

fn main() {print_labeled_measurement(5, 'h');
}
​
fn print_labeled_measurement(value: i32, unit_label: char) {println!("The measurement is: {value}{unit_label}");
}

这个例子创建了一个名为 print_labeled_measurement 的函数,它有两个参数。第一个参数名为 value,类型是 i32。第二个参数是 unit_label ,类型是 char。然后,该函数打印包含 valueunit_label 的文本。

尝试运行代码, 结果如下:

因为我们使用 5 作为 value 的值,h 作为 unit_label 的值来调用函数,所以程序输出包含这些值。

3.语句和表达式

函数体由一系列的语句和一个可选的结尾表达式构成。目前为止,我们提到的函数还不包含结尾表达式,不过已经见过作为语句一部分的表达式。因为 Rust 是一门基于表达式(expression-based)的语言,这是一个需要理解的(不同于其他语言)重要区别。其他语言并没有这样的区别,所以让我们看看语句与表达式有什么区别以及这些区别是如何影响函数体的。

语句Statements)是执行一些操作但不返回值的指令。 表达式Expressions)计算并产生一个值。

实际上,我们已经使用过语句和表达式。使用 let 关键字创建变量并绑定一个值是一个语句。

例如在下面的代码中, let y = 6;是一个语句。

fn main() {let y = 6;
}

函数定义也是语句,上面整个例子本身就是一个语句。

语句不返回值。因此,不能把 let 语句赋值给另一个变量,比如下面的例子尝试做的,会产生一个错误:

fn main() {let x = (let y = 6);
}

编译执行后,产生的错误如下:

let y = 6 语句并不返回值,所以没有可以绑定到 x 上的值。这与其他语言不同,例如 C 和 Ruby,它们的赋值语句会返回所赋的值。在这些语言中,可以这么写 x = y = 6,这样 xy 的值都是 6;Rust 中不能这样写。

表达式会计算出一个值,并且你将编写的大部分 Rust 代码是由表达式组成的。

看一下下面的代码:

fn main() {let y = {let x = 3;x + 1};
​println!("The value of y is: {y}");
}

函数调用是一个表达式。宏调用是一个表达式。用大括号创建的一个新的块作用域也是一个表达式

上面代码中, 这个表达式:

{let x = 3;x + 1
}

是一个代码块,它的值是 4。这个值作为 let 语句的一部分被绑定到 y 上。通过调试代码, 可以看到语句执行情况, 如图:

当指令执行到x+1时,x的值为3, y没有值, 当执行完x+1后, 注意观察x和y的值,如图:

注意 x+1 这一行在结尾没有分号,与你见过的大部分代码行不同。表达式的结尾没有分号。如果在表达式的结尾加上分号,它就变成了语句,而语句不会返回值。在接下来探索具有返回值的函数和表达式时要谨记这一点。

4.具有返回值的函数

函数可以向调用它的代码返回值。可以不对返回值命名,但要在箭头(->)后声明它的类型。在 Rust 中,函数的返回值等同于函数体最后一个表达式的值。使用 return 关键字和指定值,可从函数中提前返回;但大部分函数隐式的返回最后的表达式。这是一个有返回值的函数的例子:

fn five() -> i32 {5
}
​
fn main() {let x = five();
​println!("The value of x is: {x}");
}

five 函数中没有函数调用、宏、甚至没有 let 语句 —— 只有数字 5。这在 Rust 中是一个完全有效的函数。注意,也指定了函数返回值的类型,就是 -> i32。尝试运行代码;输出如下:

five 函数的返回值是 5,所以返回值类型是 i32。仔细检查一下这段代码。有两个重要的部分:首先,let x = five(); 这一行表明使用函数的返回值初始化一个变量。因为 five 函数返回 5,这一行与如下代码相同:

let x = 5;

其次,five 函数没有参数并定义了返回值类型,不过函数体只有单单一个 5 也没有分号,因为这是一个表达式,我们想要返回它的值。

看下面的例子:

fn main() {let x = plus_one(5);
​println!("The value of x is: {x}");
}
​
fn plus_one(x: i32) -> i32 {x + 1
}

运行代码会打印出 The value of x is: 6

但如果在包含 x + 1 的行尾加上一个分号,把它从表达式变成语句, 代码如下:

fn main() {let x = plus_one(5);
​println!("The value of x is: {x}");
}
​
fn plus_one(x: i32) -> i32 {x + 1;
}

我们将看到一个错误,如图:

主要的错误信息,“mismatched types”(类型不匹配),揭示了代码的核心问题。函数 plus_one 的定义说明它要返回一个 i32 类型的值,不过语句并不会返回值,使用单位类型 () 表示不返回值。因为不返回值与函数定义相矛盾,从而出现一个错误。在输出中,Rust 提供了一条信息,可能有助于纠正这个错误:它建议删除分号,将会修复这个错误。

相关文章:

Rust编程基础之函数和表达式

1.Rust函数 在之前的文章中,我们已经见到了一个函数:main函数, 它是很多程序的入口点。也见过 fn 关键字,它用来声明新函数。 Rust 代码中的函数和变量名使用 snake case 规范风格。在 snake case 中,所有字母都是小写并使用下划线分隔单词。这是一个包…...

关于preempt count的疑问

Linux中的preempt_count - 知乎 https://www.cnblogs.com/hellokitty2/p/15652312.html LWN:关于preempt_count()的四个小讨论!-CSDN博客 主要是参考这些文章 之前一直认为只要是in_interrupt()返回非0值,那么就可以认为当前在中断上下文。即…...

Windows 开启 Kerberos 的火狐 Firefox 浏览器访问yarn、hdfs

背景:类型为IPA或者MIT KDC,windows目前只支持 firefoxMIT Kerberos客户端的形式,其他windows端浏览器IE、chrome、edge,没有办法去调用MIT Kerberos Windows客户端的GSSAPI验证方式,所以均无法使用 Windows 开启 Kerb…...

华为云资源搭建过程

网络搭建 EIP: 弹性EIP,支持IPv4和IPv6。 弹性公网IP(Elastic IP)提供独立的公网IP资源,包括公网IP地址与公网出口带宽服务。可以与弹性云服务器、裸金属服务器、虚拟IP、弹性负载均衡、NAT网关等资源灵活地绑定及解绑…...

突破防火墙的一种方法

当Linux防火墙阻止来自某个ip的数据时,它应该是根据ip数据报里“源IP地址”字段取得的对方ip吧,那对方就不能通过篡改“源IP地址”来绕过防火墙吗?NAT模式下的路由器就修改了这个字段。 但这样的话,攻击者是收不到服务器返回的数…...

Docker 多阶段构建的原理及构建过程展示

Docker多阶段构建是一个优秀的技术,可以显著减少 Docker 镜像的大小,从而加快镜像的构建速度,并减少镜像的传输时间和存储空间。本文将详细介绍 Docker 多阶段构建的原理、用途以及示例。 Docker 多阶段构建的原理 在传统的 Docker 镜像构建…...

【开题报告】基于Spring Boot的家装产品展示交易平台的设计与实现

1.研究背景和目的 随着人们对居住环境舒适度和个性化需求的不断提升,家装市场正逐渐发展成为一个重要的消费领域。为了满足消费者对家装产品的需求,建立一个高效、可靠的家装产品展示交易平台变得尤为重要。本项目旨在通过使用Spring Boot框架&#xff…...

MacOS安装git

文章目录 通过Xcode Command Lines Tool安装(推荐)终端直接运行git命令根据流程安装先安装Command Lines Tool后再安装git 官网下载二进制文件进行安装官方国外源下载二进制文件(不推荐)国内镜像下载二进制文件(推荐)安装git 通过Xcode Command Lines Tool安装(推荐) 简单来讲C…...

京东协议算法最新版

环境准备 1 com.jingdong.app.mall11.6.4 入口定位 逆向分析,发现 params 里面有一个 sign 以及请求头里面有一个 jdgs 首先我们发现京东的 sign 是 32 位的,猜测其可能是 md5 之类的 hash 算法,既然是 hash 算法,那么就大概率…...

软考系统架构设计师案例分析知识汇总

软件架构风格 △△△ 软件架构风格是描述某一类特定应用领域中软件系统组织方式和惯用方式。组织方式描述了系统的组成构件和这些构件的组织方式,惯用模式则反映众多系统共有的结构和语义。 面向对象架构风格的特征是将数据表示和基本操作封装在对象中。这种模式的构件是对象…...

MyBatis-plus 代码生成器

具体代码 application.yaml server:port: 8081 #自定义端口号spring:datasource:url: jdbc:mysql://localhost:3306/itcast?useUnicodetrue&characterEncodingutf-8&serverTimezoneGMT%2B8username: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driver…...

运维常识——网络

内网,公网IP 内网IP为专网IP 因为网络资源(IP地址不够,所以引出来了内网IP和IPv6) 内网IP和公网IP之分是为了减缓IP地址不够使用的情况 一般设置代理服务器 设置两张网卡 一张对外一张对内 内部主机将数据转发到内网卡&#…...

《研发效能(DevOps)工程师》课程简介(一)丨IDCF

为贯彻落实《关于深化人才发展体制机制改革的意见》,推动实施人才强国战略,促进专业技术人员提升职业素养、补充新知识新技能,实现人力资源深度开发,推动经济社会全面发展,根据《中华人民共和国劳动法》有关规定&#…...

OMV 介绍及安装

# Time: 2023/11/02 #Author: Xiaohong # 运行电脑: Lenovo X201I (Intel(R) Core(TM) i3 CPU M 370 2.40GHz) # 功能: OMV 介绍及安装 导图 若OMV6 安装Extras 插件失败,可以参考 OMV6 安装Extras 插件失败的解决方法...

JAVA 实现PDF转图片(spire.pdf.free版)

1.引入jar包 导入方法1: 手动引入。将Free Spire.PDF for Java下载到本地,解压,找到lib文件夹下的Spire.PDF.jar文件。在IDEA中打开如下界面,将本地路径中的jar文件引入Java程序: 导入方法2:如果您想通过…...

高效学习工具之AnkiMobile新手入门指南(ios端,包括ipad、ihpone设备)————创建、使用、备份、设置参数、相关资料

文章目录 0 背景0.1 闭环学习0.2 什么是anki0.3 anki践行者经验分享 1 开始使用1.1 导入1.2 创建空白组1.3 创建卡片1.3.1 利用anki创建卡片的两种方法1.3.2 复习材料分类 1.4 筛选(做减法,拆分学习(做子卡牌集合))&am…...

LiveMeida视频接入网关

一、产品简介 视频接入网关主要部署在视频存储节点或视频汇聚节点,面向不同用户,主要用于对接不同厂家、不同型号的摄像机设备,获取摄像机视频后,以统一标准的视频格式和传输协议,将视频推送至上层联网/应用平台。可广…...

我和云栖有个约会

文章目录 云栖大会体验与感受大模型的体验感受 对大会的期待 云栖大会 云栖大会是是阿里巴巴集团主办的年度技术盛会,是云计算、大数据、人工智能等前沿技术产业发展的见证者、参与者和推动者。2023年的云栖大会于10月31日在杭州开幕,吸引了全球的技术专…...

模拟官网编写自定义Grafana Dashboard

前言 我们想编写自定义的Dashboard,类似于官网那样下载的Dashboard,并且能移值到机器主机,如何实现了? ## 官网dashboard https://grafana.com/grafana/dashboards/ 编写 先在虚拟机写好Dashboard 然后下载。json文件如下: {…...

组件局部注册和全局注册

普通组件的注册使用-局部注册 1.特点&#xff1a; 只能在注册的组件内使用 2.实现效果 3.步骤&#xff1a; 创建.vue文件&#xff08;三个组成部分&#xff09;在使用的组件内先导入再注册&#xff0c;最后使用 4.使用方式&#xff1a; 当成html标签使用即可 <组件名&…...

BinaryBomb通关后,我总结了这6个Linux调试与逆向的‘骚操作’

BinaryBomb通关后&#xff0c;我总结了这6个Linux调试与逆向的‘骚操作’ 在计算机系统基础课程中&#xff0c;BinaryBomb实验堪称是检验学生调试与逆向能力的"试金石"。作为一位刚刚通关的"拆弹专家"&#xff0c;我想分享那些教科书上不会教、却能让你效率…...

云厂商AI基础设施争夺战:Bedrock、Azure AI Studio与Vertex AI深度对比

1. 项目概述&#xff1a;一场没有硝烟的AI基础设施争夺战你打开云厂商控制台&#xff0c;发现“Bedrock”“Azure AI Studio”“Vertex AI”这些名字突然变得比以前更醒目&#xff1b;你翻看技术团队的采购清单&#xff0c;GPU实例价格单旁多了一行加粗标注&#xff1a;“含专属…...

5个必学的Rainmeter桌面监控技巧:打造个性化Windows系统仪表盘

5个必学的Rainmeter桌面监控技巧&#xff1a;打造个性化Windows系统仪表盘 【免费下载链接】rainmeter Desktop customization tool for Windows 项目地址: https://gitcode.com/gh_mirrors/ra/rainmeter Rainmeter作为Windows平台上最强大的桌面自定义工具&#xff0c;…...

突破语言壁垒:AI驱动视频学习工具LLPlayer完全指南

突破语言壁垒&#xff1a;AI驱动视频学习工具LLPlayer完全指南 【免费下载链接】LLPlayer The media player for language learning, with dual subtitles, AI-generated subtitles, real-time translation, and more! 项目地址: https://gitcode.com/gh_mirrors/ll/LLPlayer…...

KMS智能激活工具:三步永久激活Windows和Office系统完整指南

KMS智能激活工具&#xff1a;三步永久激活Windows和Office系统完整指南 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为Windows系统频繁弹出激活提示而烦恼吗&#xff1f;Office文档突然变…...

NVIDIA Profile Inspector完整指南:免费解锁显卡隐藏性能的终极工具

NVIDIA Profile Inspector完整指南&#xff1a;免费解锁显卡隐藏性能的终极工具 【免费下载链接】nvidiaProfileInspector 项目地址: https://gitcode.com/gh_mirrors/nv/nvidiaProfileInspector 你是否曾经想过&#xff0c;为什么你的NVIDIA显卡明明性能不错&#xff…...

从一家工厂的产品图、SKU 宽度和产品页,能读出哪些经营信息?一份给采购方和上游销售员的读图手册

采购、品牌方、上游销售员常遇到同一种困惑&#xff1a;打开一家"工厂"的店铺&#xff0c;产品图漂亮、SKU 铺得一大屏、参数行行写满&#xff0c;但聊几句发现对方根本不是工厂&#xff0c;是转单贸易商&#xff1b;或者是真工厂&#xff0c;但定位和需求完全错位。…...

java springboot-vue加油站管理系统的设计与实现

目录同行可拿货,招校园代理 ,本人源头供货商项目背景技术架构核心功能模块系统特色部署方式应用场景项目技术支持源码获取详细视频演示 &#xff1a;同行可合作点击我获取源码->->进我个人主页-->获取博主联系方式同行可拿货,招校园代理 ,本人源头供货商 项目背景 加…...

记录人生第一个Linux内核Patch被采纳的经历

最近运气不错&#xff0c;提交的一个关于 Linux 内核 SMMUv3 驱动的补丁&#xff08;Patch&#xff09;被采纳了。虽然只是一个边界条件的微调&#xff0c;但作为自己的第一个 Patch&#xff0c;过程还挺有意思的&#xff0c;中间也暴露出自己不少技术盲区。趁着记忆热乎&#…...

第一学期结果

关注 1.从安涛老师前三期视频中了解了方向2.从b站了解了555的内部结构3.仿真。4.低通滤波器的基本原理&#xff1a;一、核心定义只允许低频信号顺利通过&#xff0c;阻挡、衰减高频信号的电路。 你电路里作用&#xff1a;滤掉方波里的高频谐波&#xff0c;留下低频基波&#xf…...