rust 学习历程(一)

最近想要学习 rust,记录一下 rust 的学习历程。预计最终目标是用 rust 完成一个简单的 os 内核。由于个人 golang 用的比较多,会尽可能将 rust 相关的功能和 golang 进行对比。

希望能通过 rust 接触更多的编程思想,golang 写的都不会用范型了。

NOTE: 整个学习历程可能会比较跳跃

Get Started

安装 rust 一帆风顺,cargo 还是很好用的 (当然可能是短期内没有踩到坑)。rust 的包管理几乎完爆了 golang,想起过去折腾 golang 的包管理还是很心累。再一想到过段时间可能又要从 dep 换掉真的令人内心爆炸。

以下是 rust hello world!

1
2
3
fn () {
println!("Hello, world!");
}

关于这段程序,我遇到了三个问题:

  1. println 为什么后面加了 !
  2. 最后的分号是否可选
  3. println 文档在哪

Marco

macro_rules!

println! 表示这个是一个 macro。这让我想起了被 C 的 #define 支配的日子。macro 本质就是代码替换,但是骚操作太多,很多语言完全放弃了 macro 这种特性(比如 golang)。

rust 中 macro 的语法如下,( $( $x:expr ),* ) 涉及到了 模式匹配 的概念。

TODO: 模式匹配

1
2
3
4
5
6
7
8
9
10
11
macro_rules! vec {
( $( $x:expr ),* ) => {
{
let mut temp_vec = Vec::new();
$(
temp_vec.push($x);
)*
temp_vec
}
};
}

macro 展开后如下,其中 $()* 类似 regex,表示生成任意次,次数对应匹配 ( $( $x:expr ),* ) 多少次,匹配 1, 2, 3 就生成了 3 次。

1
2
3
4
5
6
7
8
9
let v: Vec<u32> = vec![1, 2, 3];

let v: Vec<u32> = {
let mut temp_vec = Vec::new();
temp_vec.push(1);
temp_vec.push(2);
temp_vec.push(3);
temp_vec
};

然后小萌新突然发现 rust 说 macro_ruls! 有很多问题,会被废弃。
emmmm… 反正 golang 都甚至没有 macro

procedural macro

还有一种 macro 叫做 procedural macro,有以下三种情况

  • Custom #[derive] macros
  • Attribute-like macros
  • Function-like macros

和上面的 macro_rule 的区别在于不是单纯的代码段替换而是接受一段 rust 代码后输出一段 rust 代码(感觉是可以自定义 macro template 逻辑的意思)

TODO: procedural macro 详解

Statement Or Expression

rust 被称为 expression languagestatementexpression 最主要的区别在于 expression 总是返回值。

在 rust 中 statement 有以下几种

  • Item: 类似各种 fn 之类的声明
  • LetStatement: let 语句
  • ExpressionStatement: 所有的 expression 加上 ; 后就成了 statment
  • MacroInvocationSemi: macro 相关的调用语句

Why println! without ; can be compiled

Hello Worldprintln! 语句的最后是可以不添加分号的,原因是 rust 默认返回最后一个 expression 的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// it's ok
fn ok {
println!("aaa")
}
// it's also ok
fn alsoOk {
println!("aaa");
println!("aaa")
}
// it's error, because expression only can be the last of fn
fn err {
println!("aaa")
println!("aaa");
}

另外 rust 中还有一个设定是 statement 会返回 ()

1
2
3
4
5
6
7
8
9
// x is [1,2,3]
let x = {
vec![1,2,3]
};

// y is ()
let y = {
vec![1,2,3];
};

个人感觉这个操作挺迷的。

Document

println 文档

文档的直观感觉还是很不错的。

At Last

TODOs:

  • 模式匹配
  • procedural macro 详解