[Rust] 三言两语理解Module System

不要急、要涨要跌比特币都会给你个痛快,关键你想利益最大化!

大家好,我是紫狮财经CEO,Hyrik老师(QQ:1516217510)。对于比特币来说,严格按照技术指标来看的话,从前天暴跌,到这两天的震荡蓄势,整体来看的话。并没有哪一天收盘价是低于46000刀的,也就是46000刀这一支撑位至今没有有效跌破。 那么按照计…

Rust 的module system容易让人摸不着头脑。The book


写了很多的内容,但是不适合有一定编码经验的人。

因为里面的内容更多的是强调module的好处,解决了什么问题,并没有对比Rust的module 系统与其他的编程语言的区别。

本文记录Rust module系统让人困惑的三个地方,方便与我有同样困惑的人,也方便我日后参考。


欢迎阅读我其他关于Rust的文章,

刻舟求剑与Pin

Rust: PhantomData,#may_dangle和Drop Check 真真假假


Module System


一个大问题总会由许多小问题组成。module system是为了定义清楚各个小问题的边界。

这样更容易和更方便的管理问题。而大问题的解法,就是把小问题的解法组合起来。


下面是Rust Module System让人困惑的三个地方。

1. project, package, crate, module的区别

project,package, crate, module这些概念感觉相似。

它们的关系是,


  1. package等同于projectcargo new <project> 会创建一个project。

  2. 一个package/project可以包含多个 binary crates和0个或者1library binary。

  3. 一个crate可以包含多个module。


当proejct 包含lib.rs,那lib.rs是library crates。bin文件夹包含的文件就是binary crates。cargo new –lib project_name生成。这个library的名字是project的名字。

当project只包含main.rs,那么它就是一个只包含binary crate的project,可以通过命令cargo new –bin project_name生成

可以认为package就是一个project,一个crate就是一个暴露给外界的逻辑单元,一个module就是一个小问题的解法。


比如下面的project 结构

[Rust] 三言两语理解Module System

client.rs和server.rs可以直接使用这个library crate。可以认为bin文件夹里面是单独的crate,它们默认依赖了这个library crate。

2. module tree是怎么生成的

project里面的module tree必须显示地指明。


而且一开始的时候,编译器看到的project的module tree仅仅含有main.rs或者lib.rs(下图右边的黄色框框),又叫做crate root。

代码crate::foo 的crate指代的就是这个crate root。

[Rust] 三言两语理解Module System

上图左边的目录树,大部分人看到文件系统已经有结构并且组织好,会下意识地认为编译器也会看到这个文件目录结构。但是实际上,编译器看到的project仅仅包含了main.rs

这一点Rust跟其他语言区别很大。比如在Java里面,你可以直接import 某个目录里面的class。在Rust,如果直接use某个目录的module是编译通不过的。报错如下

error[E0432]: unresolved import `http_server::log`
--> src/bin/main.rs:3:5
|
3 | use http_server::log;
| ^^^^^^^^^^^^^^^^ no `log` in the root

因为你还没有将log添加到crate root里面。也就是要显示地指明module tree的结构。这也就是我们经常在main.rs/lib.rs里面看到许多mod xxx的原因。

比如下面的代码,



https://github.com/Celthi/rsnova/blob/master/src/lib.rs#L20

它们的存在就是为了将project里面的modules 加到这个crate里面。

比如在main.rs 里面看到mod channel,就是将module channel加进crate的module tree来。


这点让我明白了Rust 的”be explicit“原则无处不在。


综上所述,Rust 的module tree的一种样子是,

[Rust] 三言两语理解Module System

可能有人会问为什么模块已经存在文件系统里面了,还要显示通过mod foo将模块添加到Rust里面。


可以这么理解,Rust在生成程序的时候,是由crate root去将代码包含进来。


这也就是为什么叫crate root的原因——它是根节点,从这个根节点,一点点地添加模块进来,生成整个package。

3. 父模块和子模块的包含方法

有时候一个folder里面有个mod.rs,有时候没有。这是因为mod foo的作用是告诉编译器找寻foo.rs或者foo/mod.rs,并且将找寻到的文件内容作为module foo的内容

你可以选择你喜欢的方式使用foo.rs或者foo/mod.rs。

使用文件夹foo存储modules的时候,我们可以创建一个跟文件夹同名的foo.rs来添加文件夹里面的modules,也可以在文件夹foo里面用mod.rs添加对应的modules。


所以,mod foo是将foo模块添加到project的module tree。

use foo;是将一个模块加进当前的scope


而./foo.rs或者./foo/mod.rs, 或者mod foo {…} 定义模块,它们三者是等效的。

其中./foo.rs可以使用文件夹foo用于存放子模块。./foo/mod.rs已经有文件夹foo,它也可以用于存放子模块。

所以./foo/mod.rs等效于./foo.rs加上./foo/文件夹。

我个人喜欢使用./foo.rs加上文件夹foo来组织子模块。

module的可见性,并不让人困惑,所以本文不提。workspace也比较容易理解,所以略过。

总结

Rust module system提炼为下面三点——


  • foo.rs或者foo/mod.rs, foo {… } 定义模块foo。

  • 子模块child必须在父模块在声明(mod child),不然它们就不会存在。

  • 子模块child的内容可以mod {… } 显示内联定义在父模块parent.rs里面;可以定义在./child.rs;可以定义在./child/mod.rs。其中当前文件夹是父模块所有的文件夹或者和父模块同名的文件夹。

参考文献


The Edition Guide

Mentally Modelling ModulesRust modules confusion when there is main.rs and lib.rs

本文第一章图片来源于Clear explanation of Rust’s module system

The confusion around Rust’s modules reminds me of the different ways that people…

反弹弱势的比特币大盘币友们需要注意几个关键的位置!

大家好,我是紫狮财经CEO,Hyrik老师(QQ:1516217510)。咱们先复盘一下最近几天的文章,先是周五的文章中强调的,具体币友们看下图: 周五强调,周五到周六,就算收盘不跌破46000刀,但是反弹上不去48200刀,建议币友粉丝们最少出货空仓三层等待…

Click to rate this post!
[Total: 0 Average: 0]

人已赞赏
Dfinity名家说小白百科每日优选

Dfinity 的 ICP 价格反弹,投资者重新燃起了兴趣

2021-9-14 20:59:10

名家说每日优选

小宇宙首页改版两个月,大家怎么说?

2021-9-15 21:03:32

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索