本文来自喵哥 CrLF0710 的知乎:https://zhuanlan.zhihu.com/p/105181947

大家好,这次我来说一说这门名叫 Rust 的语言的语法。推荐有一点点 Rust 基础的读者来读,其实零基础也可以读,但是可能会觉得有点枯燥。如果有一点点 Rust 基础,可能更容易理解一点。

这不能当作是一本 21 天学会 Rust 的教材,因为这里除了语法概念,真的什么都不讲。

一、编译单元:盒 (crate)

大家都知道,Rust 工具链里,最常用的两个工具就是包管理器 Cargo,和编译器 Rustc。Rust 是一门编译型语言,在 Rust 的世界里,独立完成编译的最小单元叫做 crate,没有大家公认的译法,这里暂时称为盒好了。

盒 (crate) 刚刚好是 cargo 管理的最小结构,也是 rustc 管理的最大的结构。比盒 (crate) 大的结构依次是包 (package)、空间 (workspace),这些是 cargo 的地盘,咱们在这里暂且不细说。Rustc 每次执行从一个 crate(盒) 的最外层的一个源文件生成它的目标文件。比如经典的 Hello world 程序

    // main.rs      fn main() { println!("Hello world!");}

执行

     rustc main.rs -o hello.exe

就从这个 crate 的最外层源文件 main.rs 编译生成了一个 hello.exe 的可执行文件。简单吧?

这次只学一点 Rust 语法大概不会怀孕了吧 (1)

二、盒内的世界

盒 (crate) 是树状结构。由至少一个通常扩展名为 rs 的源文件组成。如果有必要的话,它可以引用其他文件来表达树的一部分,这个我们等下会讲到。树上的节点称为条目 (item)。

刚才说到 crate 有一个最外层的源文件,这个源文件本身就隐含对应了这棵树的根节点,它是一个模块节点,是匿名的模块。模块是条目的容器,天生就是用来组织内部条目的(类比其他语言的命名空间),然后其他有几种条目也具有声明内部条目的能力,我们等下就会说到。这些条目形成了 crate 的树状结构,编译器读懂你提供的这棵树,然后把它生成 crate 类型所指定的格式的目标文件。最常用的是 rlib 和 bin 两种,分别是可重用的 Rust 风味静态库文件和可执行程序。

条目 (item) 目前(2020 年 2 月)有十四种。听起来很多但是我来帮你把它们稍微归类一下就会发现其实很简单。

第一类条目就是刚才说到的模块条目,它是它是用来组织其他条目的,类似文件夹层级。一种写法是内容直接写在花括号内。另一种写法是由它根据一套规则指向磁盘上的另一个文件,作为它的内容。

第二类条目用来定义一些用户定义类型:主要有结构体定义、枚举体定义、联合体定义这几种。结构体、枚举体、联合体是 Rust 里的三种用户定义类型。要注意,由于 Rust 里对泛型的广泛使用(三句不离泛型),结构体定义、枚举体定义、联合体定义这些定义出来的类型在非泛型的情况下是一个具体类型,比如 String,在泛型的情况下则是一族具体类型,类似 Vec 这样,其中 T 是泛型参数,代入不同的泛型参数的“取值”就会得到不同的具体类型。不管是哪种,整个定义都是一个条目,是一个整体。

第三类条目也有定义类型的效果,但是定义出来的就不算是用户定义类型了。首先是类型别名定义条目,它定义一个类型别名(也支持泛型)指向其他具体类型。另外就是函数定义条目(依然支持泛型),它会自动产生一个独特的函数条目内置类型,在表达式中写这个函数的名称就可以拿到这个类型的值。

第四类条目会声明作用域为全局的值,与函数定义条目有些类似之处。首先是常数定义条目,指定名称、类型和一个常数表达式后,你就可以在表达式中用这个名称引用这个值了。然后是静态定义条目,它与常数定义条目的区别是它的值具有一个全局的存储位置,从而能够表达状态变化,可以类比其他语言中的全局变量。

第五类条目与特质 (trait) 系统相关。特质条目用来定义一个特质,特质不是类型,是一种可以与类型建立联系的抽象接口,抽象接口含有关联条目,目前共三种,关联常数条目就类似常数定义条目,关联类型别名条目就类似类型别名定义条目,关联方法条目有点像函数定义条目,但稍微有点区别。

第六类条目称为实现条目。实现分为固有实现和特质实现两种。实现条目写起来的格式很特别,有点像某些查询语言,基本上是“对于满足某某条件的某某类型 (和某某特质),提供如下的关联条目定义”的结构。这个比较复杂,后面我们会详细讲。

第七类条目用来实现导入功能。导入有三种,一种是导入其他的盒 (crate) 到全局空间中,称为外部盒 (extern crate) 条目。一种是建立一个“链接”,称为引用声明条目,类似磁盘上的符号链接或者快捷文件,形成“它虽然其实定义不是在这的,但是仿佛就在这里”的效果。这个效果在 rust 里很重要,后面还会反复说到。另一种是外部定义块条目,它用来包含其他语言(目前是 C 语言)在外部提供的定义,目前有两种,外部静态条目就类似静态条目,外部函数条目就类似函数定义条目。

当前这个赛季里的基本条目就这么多,但是实际上在 Rust 代码中有一种特例“万能牌”,那就是宏。宏的使用根据它所处的环境在语法里可以扮演各种角色。宏当然可以充当条目使用,也就是宏条目,宏条目会在编译时被编译器执行展开操作。宏调用的宏条目展开的结果也必须得到若干个条目,而宏定义的宏条目展开后会“消失”。

好啦,这一次暂且说到这里。祝大家新年愉快 ~