「Learn Rust」#0 总章
学习一门新语言之Haskell
前言
Haskell学的差不多了,也没啥事想干了
GZTime之前也跟我推荐过Rust挺好玩的
这几天看一看
一样,没有教程,只是我的笔记而已
Installation
Mac上安装只需要安装rustup即可:
1 | $ curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh |
然后更新、卸载、检查:
1 | $ rustup update |
Rust代码的后缀名是.rs
,通过rustc code.rs
来编译出二进制文件code
再运行
Cargo
通过rustup安装后自带cargo,可以通过cargo --version
检查
通过cargo new project_name
来新建一个项目,这时会在当前目录下自动生成下面的目录结构:
1 | project_name |
cargo会根据输入的项目名称新建一个文件夹,并且默认使用git进行版本控制(可以使用cargo new ... --vcs none
取消版本控制)
其中main.rs文件中就是一个Hell World程序。Cargo.toml是这个项目的配置文件:
1 | [package] |
构建、运行、发布
- 使用
cargo build
会构建这个项目,并且将可执行文件创建在target/debug/
文件夹中 - 使用
cargo run
直接构建并运行这个项目 - 使用
cargo check
检查项目,但不生产可执行文件、也不输出结果 - 使用
cargo build --release
来发布,产生但可执行文件在target/release/
文件夹中,不用于直接build,它会进行一些优化来使程序运行地更快
常见编程概念
变量
let
语句会创建一个变量,但是默认都是不可变的(immutable)。即一旦使用let创建一个变量并为其赋值,那这个变量将不允许被改动,如果在代码中改动了这个变量,那么将不会通过编译
但是可以再使用let语句来创建一个同名变量:
1 | let x = 1; |
这时,原来的x就被隐藏(shadowing)了(这种方式的前后两个x本质上还是两个变量,它们允许有着不同的数据类型)
在let后面加上mut也可以创建一个可变的变量:
1 | let mut x = 1; |
但这时x不能更改数据类型
常量
常量不同于变量,它一定是不可变的。常量通过const
关键字创建,而且需要明确指定数据类型(Rust常量命名规范是用全大写):
1 | const MAX_POINT: u32 = 100_000; |
数据类型
Rust是静态类型语言,编译器需要在编译时得到所有变量的类型,但是也可以自动推测类型。
Rust中的类型分为两种,标量(scalar)和复合(compound)
scalar
整型:
长度 | 有符号 | 无符号 |
---|---|---|
8-bit | i8 | u8 |
16-bit | i16 | u16 |
32-bit | i32 | u32 |
64-bit | i64 | u64 |
128-bit | i128 | u128 |
arch | isize | usize |
isize
和usize
是根据系统而定(32/64)
同时整型的值也可以用不同进制表示(十六进制0x
开头,八进制0o
开头,二进制0b
开头,单字节字符b
开头(b’A’)),在数值中间也可以增加_
来增强可读性,在数值结尾也可以加上类型后缀来明确类型
浮点型:
单精度浮点f32
,双精度浮点f64
布尔型:bool
,值是小写true/false
字符型:char
,四字节(使用unicode)。字符是单引号而字符串是双引号
compound
元组:
元素类型可以不同,但是整个元组的类型和各个元素的类型都有关,例如:
1 | let tup: (i32, f64, u8) = (500, 6.4, 1); |
可以通过.
加索引来访问元素:
1 | let x = tup.1 |
列表:
不同于Python/Haskell,Rust中的列表的长度也是不可变的,而且列表中的所有元素的类型也必须一致。含有五个i32类型的元素的列表的类型就可以写成[i32; 5]
同时[3; 5]
这种写法也等价于[3, 3, 3, 3, 3]
可以通过[index]
来访问元素,如lst[1]
。但如果索引超出列表元素个数,那么编译将不会报错,但运行时会报错
函数
通过fn
关键字来定义函数,参数的类型必须指定,如果有返回值,返回值的类型也要在()后面用-> type指定。返回值可以在函数中途直接return返回,也可以在函数结尾直接写出要返回的值(不加分号,此时是表达式而不是语句),比如:
1 | fn plus_one(x: i32) -> i32 { |
同样,用{}括上的代码块也是一个表达式,它也可以有返回值:
1 | let x = 5; |
控制流
条件
常规的if语句,比如:
1 | if a == 1 { |
不同于Haskell,它可以没有else只有if
if语句也可以用在let上,这时{}中要是一个表达式而不是语句,即不带分号:
1 | let number = if condition { |
循环
loop:
使用loop会将块一直循环直到遇到break,也可以从loop循环返回值,比如:
1 | let mut counter = 0; |
while:
1 | while condition { |
for:
1 | for element in lst.iter() { |
所有权
鸽了,明天再写
Reference
「Learn Rust」#0 总章