3通用编程范式
[1][Rust语言入门视频教程,Rust编程入门视频教程(视频)](https://www.bilibili.com/video/BV1hp4y1k7SV)
[2][Rust 程序设计语言 简体中文版(文档)](https://kaisery.github.io/trpl-zh-cn/ch07-05-separating-modules-into-different-files.html)
3 通用编程范式
- 3.1 - 变量与可变性
- 3.2 - 数据类型:标量类型
- 3.3 - 数据类型:复合类型
- 3.4 - 函数和注释
- 3.5 - 控制流
3.1 - 变量与可变性
变量
变量默认是不可改变的(immutable),这是 Rust 提供给你的众多优势之一。
fn main() {
let x = 5;
println!("The value of x is: {x}");
x = 6;
println!("The value of x is: {x}");
}
=>> ❌
报错:x = 6; | ^^^^^ cannot assign twice to immutable variable
fn main() {
let mut x = 5;
x = 6;
}
=>> ✅
常量
示例
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
隐藏
我们可以定义一个与之前变量同名的新变量,编译器将看到第二个变量,第二个变量 “隐藏” 了第一个变量。
示例
fn main() {
let x = 5;
let x = x + 1;
{
let x = x * 2;
println!("The value of x in the inner scope is: {x}");
}
println!("The value of x is: {x}");
}
=>>
The value of x in the inner scope is: 12
The value of x is: 6
隐藏于mut的区别:
- 重新赋值如果不是mut,则会报错;而且隐藏后还是不可变类型
- 隐藏可以改变数据类型
let spaces = " "; // 字符串类型
let spaces = spaces.len(); // 数字类型
3.2 - 数据类型:标量类型
rust是 静态类型(statically typed)语言,也就是说在编译时就必须知道所有变量的类型。
标量类型
类型 |
---|
整数类型 |
浮点类型 |
布尔类型 |
字符类型 |
表格 3-1: Rust 中的整型
长度 | 有符号 | 无符号 |
---|---|---|
8-bit | i8 | u8 |
16-bit | i16 | u16 |
32-bit | i32 | u32 |
64-bit | i64 | u64 |
128-bit | i128 | u128 |
arch | isize | usize |
- 有符号数字范围:-(2n - 1) 到 2n - 1 - 1
- 无符号数字范围:0 到 2n - 1
isize
和usize
类型依赖运行程序的计算机架构:64 位架构上它们是 64 位的, 32 位架构上它们是 32 位的,使用场景是对某种集合进行索引操作
数字字面值
表格 3-2: Rust 中的整型字面值
数字字面值 | 例子 |
---|---|
Decimal (十进制) | 98_222 |
Hex (十六进制) | 0xff |
Octal (八进制) | 0o77 |
Binary (二进制) | 0b1111_0000 |
Byte (单字节字符)(仅限于u8 ) | b'A' |
整型溢出
溢出会有两种情况:
- debug 模式编译时,Rust 检查这类问题并使程序 panic
- 在 release 构建中,Rust 不检测溢出,相反会进行一种被称为二进制补码包装(环绕),即值
256
变成0
,值257
变成1
,依此类推
浮点类型
rust中,浮点数采用 IEEE-754 标准表示。f32
是单精度浮点数,f64
是双精度浮点数(默认)。
Rust 中的所有数字类型都支持基本数学运算:加法、减法、乘法、除法和取余。整数除法会 向下舍入
到最接近的整数。
字符类型
占四个字节大小,用单引号声明
let c = 'z';
let z: char = 'ℤ'; // with explicit type annotation
let heart_eyed_cat = '😻';
3.3 - 数据类型:复合类型
Rust 有两个原生的复合类型:元组(tuple)和数组(array)。
元组类型
将多个其他类型的值组合进一个复合类型的主要方式。元组长度固定:一旦声明,其长度不会增大或缩小。
let tup: (i32, f64, u8) = (500, 6.4, 1);
元组解构
let tup = (500, 6.4, 1);
let (x, y, z) = tup;
点号访问
let x: (i32, f64, u8) = (500, 6.4, 1);
let five_hundred = x.0;
=>> 500
数组类型
与元组不同,数组中的每个元素的 类型必须相同
let a = [1, 2, 3, 4, 5];
类型声明
let a: [i32; 5] = [1, 2, 3, 4, 5];
// 5个元素,都是i32类型
let a = [3; 5];
// 5个元素,值都是3
3.4 - 函数和注释
Rust 代码中的函数和变量名使用 snake case 规范风格
fn main() {
another_function(5);
}
fn another_function(x: i32) {
println!("The value of x is: {x}");
}
- 在函数签名中,必须 声明每个参数的类型
- 函数体由一系列的语句和一个可选的结尾表达式构成
语句和表达式
Rust 是一门基于表达式(expression-based)的语言,这是一个需要理解的(不同于其他语言)重要区别
名称 | 例子 | 错误例子❌ |
---|---|---|
语句(Statements)是执行一些操作但不返回值的指令 | let y = 6; | x = y = 6,因为y=6在rust中没有返回值 |
表达式(Expressions)计算并产生一个值,可以被赋值 | 函数调用是一个表达式。宏调用是一个表达式。用大括号创建的一个新的块作用域也是一个表达式 |
let y = {
let x = 3;
x + 1
};
=>> y is 3
表达式的结尾没有分号。如果在表达式的结尾加上分号,它就变成了语句,而语句不会返回值
注释
单行注释 | 文档注释 |
---|---|
// | /// |
3.5 - 控制流
if 表达式
if number % 4 == 0 {
println!("number is divisible by 4");
} else if number % 3 == 0 {
println!("number is divisible by 3");
} else {
println!("number is not divisible by 4, 3, or 2");
}
注意,代码中的条件 必须 是 bool
值,否则会到一个错误
在 let
语句中使用 if
因为 if
是一个表达式,我们可以在 let
语句的右侧使用它
let number = if condition { 5 } else { 6 };
循环
Rust 有三种循环:loop
、while
和 for
loop重复循环
loop {
println!("again!");
}
从循环返回值
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
循环标签:在多个循环之间消除歧义
注意标签是一个单引号
let mut count = 0;
'counting_up: loop {
println!("count = {count}");
let mut remaining = 10;
loop {
println!("remaining = {remaining}");
if remaining == 9 {
break;
}
if count == 2 {
break 'counting_up;
}
remaining -= 1;
}
count += 1;
}
println!("End count = {count}");
while条件循环
while number != 0 {
println!("{number}!");
number -= 1;
}
使用 for
遍历集合
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is: {element}");
}
for number in (1..4).rev() {
println!("{number}!");
}
(1...4) 表示产生随机数1~4(左闭右开)
rev表示反转