Rust 语言学习笔记(二)

再继续快速学习一下 Rust 的以下几个知识点,就可以开始着手做点小工具了

  1. 基本数据类型
  2. 复合数据类型
  3. 基本的流程控制

Rust 设计为有效使用内存考虑的,它提供了非常细力度的数据类型,如整数分为有无符号,宽度从 8 位到 128 位,分别表示为 i8, u8, u128 等。浮点数有 f32 和 f64,以及 bool 和 range 类型。

元组

元组和 Python 的元组用法类似,Immutable, 可混合类型

数组

数组类型中的元素类型相同,表示为  [T; n], T 为类型,n 为元素个数

切片(Slice)类型

相同类型但不同长度的数组是不同的类型,如 [T; 1], [T; 2], [T; 3], 但它们的 Slice 类型都表示为 &[T]. Rust 的切片与 Python 同名概念类似

&[i32], &str 是 slice1, slice2, slice3 的推断类型,Slice 是一个视图,编译期无法确定长度。

Rust 不同宽度的类型之间不会自动转换的

不同宽度类型之间比较大小也不允许。

结构体类型

Rust 仍然延续了 C 的结构体

枚举类型

struct 和 enum 都支持用 impl 块给它们附加方法。

有有参数的枚举

输出

Yellow("黄"), Yellow("Y"), y1==y2?: false, y1==y3?: true

黄可以黄的不一样,Enum 可以这样用于模式匹配

Rust 的标准库 std::collections 提供了 4 种支持泛型的容器类型, Vec<T>, VecDeque<T>, LinkedList<T>, HashMap<K, V>, BTreeMap<K, V>, HashSet<T>, BTreeSet<T>, Binaryheap<T>。

Vec 的初始容量是 0, 不指定 mut 的话,对  v 的内容都不可修改。调用 v.push() 往其中添加元素过程中,v.len 与 v.buf.cap 之间的关系

  1. 0 -> 0
  2. 1 ~4 -> 4
  3. 5 ~ 8 -> 8
  4. 9 ~ 16 -> 16
  5. 17 ~ 32 -> 32

由此可见,至少从目前的 Vec 实现 (Rust 1.75), Vec 只在容量不足时增长,并且每次翻倍。这种实现效率会有两个问题

1) 扩容太频繁, 消耗资源, Vec 新创建一个 2 倍容量的底层数组,并将现有元素移新缓冲中去

2) 元素越多, v.len 与 v.buf.cap 差值越大,也就造成 Buffer 中浪费的空间就越大. 比如元素数量为 4096 时,再添加一个元素就扩容到了 8092,这时实际使用 4097, 空闲 4095

所以使用 Vec 最好预先估算好容量,或用 LinkedList,如用下面的方式声明 Vec

可用 vec! 宏来声明 Vec

Vec 的基本操作有 v[index], get(index), push(value), pop(), remove(index) 等。get(index) 得到的是一个 Option[&i32): Some(value) 或 None, 和 Scala 相似的 Option

其他的类型不具体说明,用到时再查 API,单独说一个 HashMap 的 map.insert(key, value) 和 entry(key).or_insert(value) 操作

  1. map.insert(key, value): 不存在 key, 插入新的键值对,已存在 key 则更新对应值, 总是覆盖旧值
  2. entry(key).or_insert(value):不存在 key, 插入新的键值对,已存在 key 则不作任何操作, 不覆盖旧值

字符串本质上是字符序列,分不可变的 str 和可变的 String

字符串(str 和 String)

&str 的创建

String 本质上是一个字段为 Vec<u8> 的结构体,声明为

它是可变的,字符串内容在堆中,由字符串长度读取到实际内容。创建 String 的方式有

String 的 vec buf 容量也是成倍的增长, 只是 buf 为零时第一次增长不同, 例如下面的代码

如果 x <=8, push_str 之后, s.vec.buf 缓冲大小为 8, x > 8 的话,v.vec.buf 缓冲大小就是 x。String 还可用 "+" 连接 &str 字符串,它会返回新的 String

format! 宏可连接 str 和 Strign

Rust 的 String 不能直接使用索引(s[idx]方式) 来访问其中的字符, 字符串迭代分 bytes() 和 chars() 两种方式。bytes() 迭代出来的是字节的整数值. len() 获取的是以字节为单位的长度。更多 String 的操作就查 API 吧。

数字字面的类型用后缀来表示,所 2u8, 1.2f32. Rust 不支持 ++, 和 -- 操作。Rust 的各种算术运算,关系运算,逻辑运算,位运算和 C 和 Java 是一样的,运算优先级也没必要去记,知道乘除优先级大于加减就够了,其他的时候就加括号吧。

Rust 的流程控制

条件语句:if - else if - else 和 Java 的用法类似,但  Rust 的 if-else 还是个表达式,是有返回值的

循环语句有三种:

  1. loop {...} 其中加条件执行 break,有类似 Java 的 do {...} while(true) 类似功用
  2. while true {...}
  3. for count in 1..=10 {...}

Rust 循环中的 break, continue 和 Java 类似,不过 break 还能有返回值

要在遍历时修改元素内容,用

不推荐用 index 去访问集合,两原因: 1) index 要求 Rust 去做越界检查,影响性能,  2) 安全, for loop 访问一次可让集合下次不可用

break + label 跳出外层循环

break 的返回值

n 的值为 123

Rust 有现代语言的模式匹配功能,用 match, Rust 没有 switch..case 语句。Rust 的 match 必须穷举所有可能性,默认分支用 _ 可放在最后。

也可以用 match 来匹配 Some(7), None 等 Option<i32> 值.

匹配 Option 时自动推断类型也有意思,比如

age 推断为 Option<i32>, 所以 Some(6) 也是 Some(i32), 如果把 Some(6) 改为 Some(6i8), age 也会被重新推断为 Option<i8>。要是不让 age 自动推断,写成

以上代码无法通过编译

let 是变量绑定(变量声明), if let 和  while let 模式匹配它 if 和 while 在判断条件的同时还能进行变量的绑定,这与 Scala 的 case Some(x) 类似。

只要不是 None 就能匹配为 Some(x), 同时捕获 value 中的值绑定到 x

if let 像是下面的 match 语法糖

let Some(x) 的另类用法

while let 也是一样的

它相当的 match 写法是

如果把 if let, while let 靠向 if, while 语句去理解,它们后面要求的是一个 bool 值,就会有疑问,为什么

if let Some(x) = value 中的 let Some(x) = value 只有有值时整体才为 true 呢?同样的在

while let Some(value) = vec.pop() 中为什么 let Some(value) = vec.pop() 有值时整体才为 true。

后记:

Rust 变量默认是 Immutable, 那是来真的,没有用 mul 修饰的话,变量的内容也是无法修改的,这与 Java 不同。

println! 宏后端调用了 std::fmt::format 宏,它的具体用法见 Rust 官方的 Module std::fmt, 它像 Python 的 format 那样可以指定输出格式,用序号或命名变量,它与 to_string() 方法,fmt::Display, fmt::Debug trait 相关。

Rust 没有构造函数的概念,许多类型实现了 new() 静态方法(这不是 Rust 语言的一部分),创建一个类型一般用 Complex {re: 2.1, im:-1.2} 或 Complex::new(11.1, 22.2) 两种方式。

Rust 的 if, match 都是表达式,是有返回值的, {} 也是有返回值

在 Rust 中,后面不加 ; 分号的是表达式(Expression),有返回值,没 ; 分号的是语句(Statement),无返回值(或说返回值为 Unit), return x; 本身是一条句,但 return 表达了返回值。

本文链接 https://yanbin.blog/rust-language-learning-2/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments