请选择 进入手机版 | 继续访问电脑版
Mozilla

火狐社区

登录    注册

QQ互联

Rust 是什么?漫画图解让你一目了然(上篇)

yingliu Mozilla员工 发表于 2019-2-28 16:13:26 | 显示全部楼层 [复制链接]
2 7094
本帖最后由 yingliu 于 2019-3-1 11:44 编辑

作者:Lin ClarkRust 团队

Rust 2018 的第一版已于去年 12 月底正式发布。这一版的 Rust 特别强调了提高 Rust 开发的生产力。

01_01-rust2018-768x843.png

不过,除了可以提高效率以外,我们很难具体形容 Rust 2018 的内涵。

有人认为它是新版本的编程语言。虽然这么说没错,但也不完全对。原因是,如果它是新版的编程语言,其管理版本的方法有别于其他语言。

以绝大多数的编程语言来说,只要一推出新版本,所有新功能和特点都会加到新版本中,而旧版则不会有新功能。

Rust 的版本更新模式则不同。这是因为受到 Rust 语言演进模式的影响,所有的新功能几乎都与原 Rust 版本完全兼容,而不需重大的更新。这也意味着不用把新功能限制在 Rust 2018 的程序代码中,而新版本的编译程序(complier)将继续支持「Rust 2015 模式」,也就是你默认使用的模式。

不过,为了推动 Rust 语言的进展,有时候必须增加新东西(如:新的语法),而这些新语法可能在现有程序代码库中造成问题。

我们以 async/await 为例。Rust 本来没有 async 和await 的概念,但事实证明这些基本语法组件很管用,可以简化异步代码的编写过程,也不会使程序代码变得太笨重。

为了添加此功能,我们将async 和 await 增加为关键词,但同时也要避免导致旧码失效……可能会把 async 或 await 当成变量名称(variable names)的程序代码。

因此,我们已将 async 和 await 两个关键词加入 Rust 2018,虽然 async/await 的功能尚未实现,但已预留其关键词。接下来三年开发工作(如:增加新关键词)所需的重大变更都将于 Rust 1.31 中一步到位。

01_02-breaking-changes-02-768x543.png

虽然 Rust 2018 有重大变更,但这不代表你的程序代码会有问题。就算你的程序代码有 async 或 await 的变量名,它仍将继续执行编译。除非你另做指示,否则编译程序仍会认定你要它照过去同样的方式来编译程序代码。

不过,当你想使用这些重大的新功能时,你可选择转换成 Rust 2018 模式。你只需执行 cargo fix,它便会告诉你是否需更新程序代码才能使用新功能。它也可以自动完成必要的更新,然后你可将 edition=2018 加到 Cargo.toml 来设置和使用新的功能。

Cargo.toml 的版本说明(edition specifier)无法套用到你的整个项目……它不适用于管理你的相依关系(dependencies)上,因为它在设计上只限于那一个程序代码包。也就是说,你能够一次拥有具备 Rust 2015 和 Rust 2018 的 crate graphs。

01_03-crate-graph-768x506.png

因为这个缘故,虽然 Rust 2018 已经上线,它看起来还是和 Rust 2015 差不多。大多数的更新都将同时于 Rust 2018 与 Rust 2015 上线。只有少数需重大变更的功能不支持 Rust 2015。

01_04-rust2018-only-768x446.png

Rust 2018 带来的不仅是针对核心语言的更新,绝非如此。

Rust 2018 努力提高 Rust 开发人员的生产力。工作效率的红利大多来自于核心语言以外的面向(如:工具的改善),以及针对特定使用场景的改进,使 Rust 成为实践那些场景最具效率的语言。

01_05-handful-of-changes-768x586.png
或者,你可把它看成一个特定的时间点,每当你需要更高性能、更轻量的实作或更高的可靠性时,Rust 2018 就能在许多使用案例中成为极具效率的语言。

01_06-as_this-768x711.png

在我们眼中,这还不是最重要的。所以,我们先来看看核心语言以外的所有事情,然后再来深入探讨核心语言。

针对特定场景的 Rust

抽象的程序语言本身不具任何生产力,必须放在使用场景中才能创造出生产力。因此,Mozilla 的 Rust 团队知道,不仅要把 Rust 变成更好的语言或工具,还需在一些领域中让 Rust 变得更易于使用。

02_01-specific-use-cases-768x578.png


在某些情况下,这意味我们必须为全新的生态系打造一套全新的工具。

在其他情况下,这代表我们必须改善生态系中既有内容并整理好文档,以利开发者快速采用。

Rust 团队组成四个工作小组,分头进行以下领域的开发:
  • WebAssembly
  • 嵌入式应用
  • 网络
  • 命令行工具

WebAssembly

工作小组必须为 WebAssembly 建立一整套全新的工具。


02_01-s-rust_loves_js-768x309.png

基于两个因素,Rust 非常适合用于 Web 开发:
  • Cargo 的crate生态系运行模式和大多数 Web 应用开发者习惯的方式一样——把一群小模块凑在一起组成更大的应用程序。这代表你可以在需要的地方轻松地使用 Rust。
  • Rust 只需要很小的内存空间,且无需 runtime 即可运行,因此,你不必加入大量的程序代码。假如你需要一个能处理大量运算工作的小模块,只要加入几行 Rust 便可加快执行速度。

通过 web-sys 和 js-sys 的 crates,你可以很简单地从 Rust 码呼叫包括 fetch 或 appendChild 在内的 Web API。还有,wasm-bindgen 可轻松支持 WebAssembly 原生环境不支持的高阶数据类型。

编写好 Rust WebAssembly 模块后,Rust 还有工具能快速将其嵌入至 Web 应用的其他部分中。你可以使用 wasm-pack 自动执行这些工具,如果你想要的话,还可将新模块推送到 npm。

你可以参考Rust 和 WebAssembly 手册,自己动手做做看。

下一步是什么?
Rust 2018 发布后,工作小组正积极拟定下一步的工作事项。他们将与社区合作,锁定下一个重点工作。

嵌入式开发

在嵌入式开发方面,工作小组的目标是要保持既有功能的稳定。

理论上,对于嵌入式开发来说,Rust已经是很好用的语言了。它为嵌入式开发人员提供了极其欠缺的现代开发工具及非常方便的高级语言功能,而且还不会过度耗用资源。因此,Rust 似乎是非常适合嵌入式开发的语言。

然而,Rust 还是有些问题。那时,必要的功能还未发布稳定版。另外,标准的函数库(library)也必须稍做改变才能用于嵌入式设备上。也就是说,开发者必须自行编译其 Rust 核心 crate(用于每个Rust 应用中作为 Rust 的基本组件——包括内建值与原始值)。

02_02-bronco-768x683.png

由于这两个因素,开发人员过去要依赖 Rust 的每日抢先版(Nightly)来工作,但因为没有针对微控制器的目标进行自动化测试,每日抢先版常无法正常执行这些目标。

为了解决这个难题,工作小组需确保稳定版本包含必要功能,以及在持续整合(CI)系统中纳入微控制器目标的测试,以避免在桌面端组件增加功能造成嵌入式组件失效的问题。

经过这些改进,Rust 的嵌入式开发已从高风险的状态朝向高生产力的方向前进。

你可参考嵌入式Rust 开发手册,亲自尝试看看。

下一步是什么?

随着过去一年的推进,Rust 已是极适合支持大量应用于嵌入式设备的 ARM Cortex-M 微处理器核心的语言。不过,还是有很多用于嵌入式设备的架构未取得完善的支持。Rust 仍需继续往前扩展,以为其他架构提供同样层级的支持。

网络

针对网络,工作小组需为 Rust语言构建核心的抽象概念——async/await。由此开发者才能在异步程序代码中使用 Rust。

网络方面的工作常需要等待。例如,你可能要等请求的响应。如果你的程序代码是同步的,在请求抵达前,执行该程序代码的 CPU 核心就要暂停工作而无法处理其他任务。但若程序代码为异步,等待响应的函数可暂停工作,CPU 核心则可继续处理其他函数。

Rust 2015 已开始支持异步 Rust 程序代码的编译。这带来许多优点。就大的层面而言,例如包括服务器应用在内的服务,程序代码便能让每台服务器处理更多联机(connections);至于小一点的事情,如在微型单线程 CPU 上运行的嵌入应用来说,异步程序代码也可更充分运用单线程的资源。

然而,这些优点也带来一个大缺点——那些程序代码无法使用借用检查器(borrow checker),而开发者也要编写出不符语言习惯(以及易于混淆)的Rust。这就是 async/await 派上用场的地方。它能为编译程序提供所需的信息,使其在各异步函数调用之间调用 borrow check。

1.31 版已纳入 async/await的关键词,但目前尚未得到实际支持。不过,大部分的工作均已完成,此功能应可在下一版本中发布。

下一步是什么?

除了为网络应用保障低阶开发的效率之外,Rust 还可为较高阶的开发工作创造生产力。

很多服务器常须处理同样的任务,它们必须剖析 URLs 或执行 HTTP 任务。如果这些任务能变成组件(变成可作为 crates 分享的通用抽象值),它们就能被轻松地汇整,以组成各式各样不同的服务器及框架。

为了推动组件开发过程,我们运用 Tide 框架打造这些组件的测试平台及使用范例。

命令行工具

在命令行工具的方面,工作小组需要将更小的低阶函数库带向更高层次的抽象,并精进一些现有的工具。

在部分 CLI 脚本的处理上,使用 bash 常是理所当然的选择。例如,如果你只需要叫出别的 shell 工具及在其中传输数据,bash 便是最好的选择。

不过,Rust 也非常适用于别种的 CLI 工具。例如,若要建立类似 ripgrep 的复杂工具、或在现有函数库的功能上外加 CLI 工具,Rust 便非常好用。

Rust 除了不需要 runtime,还支持单独的静态二进制档案的编译,所以很便于散布(distribute)。此外,它还能提供 C 和 C++ 等其他语言所无法达成的高层次抽象;单就这一点而言,Rust CLI 开发者已能享受到高效率。

那么,工作小组还有哪些方面可以改进?那就是更高层次的抽象化。

有了更高层次的抽象后,开发者就能更便捷地组合出随时可上线生产的 CLI。

这些抽象的例子之一是 human panic 函数库。若无此函式库,CLI 程序代码一旦出错,就可能输出整个 back trace,而会造成终端用户的困扰。你可以自定义错误的处理方法,但那又很费事。

相较之下,如果使用 humanpanic,输出便将自动转到错误倾印 (error dump) 档案。用户则将收到建议通报此问题及上传错误倾印文件的信息。

02_04-human-panic-768x496.png

另外,工作小组还降低了 CLI 开发的技术门坎。例如,confy 函数库可自动完成新 CLI 工具大部分的安装流程,而只会问两个问题:
  • 你的应用程序叫什么名字?
  • 你想公开 (expose) 哪些配置选项(你定义的结构可被串行化及反串行化的部分)?
答复这两个问题后,confy 就会帮你完成其他的工作。

(未完待续,见下篇

一只聪明的猪 社区新人
发表于 2019-3-6 20:45:06 | 显示全部楼层
看不懂
一只聪明的猪 社区新人
发表于 2019-3-6 20:45:22 | 显示全部楼层
看不懂
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表