Rust
Rust是由Mozilla[12]主导开发的通用、编译型编程语言。设计准则为“安全、并发、实用”,[13][14]支持函数式、並行式、程序式以及面向对象的编程风格。
編譯語言、並行计算、 函数式、指令式、 物件導向、结构化 | |
設計者 | Graydon Hoare |
實作者 | Mozilla |
2010年 | |
穩定版本 | |
型態系統 | 靜態類型、強型別、 類型推論、結構類型 |
作業系統 | Linux、macOS、Windows FreeBSD、Android、iOS等[3] |
許可證 | Apache许可证2.0及MIT許可證[4] |
文件扩展名 | .rs、.rlib |
網站 | rust-lang.org |
啟發語言 | |
Alef[5]、C#[5]、C++[5]、Cyclone[5][6] Erlang[5]、Haskell[5]、Hermes[5]、Limbo[5] Newsqueak[5]、NIL[5]、OCaml[5]、Ruby[5] Scheme[5]、Standard ML[5]、Swift[5][7] | |
影響語言 | |
C# 7[8]、Elm[9]、Idris[10]、Swift[11] |
Rust語言原本是Mozilla員工Graydon Hoare的私人計劃,而Mozilla於2009年開始贊助這個計劃 [15],並且在2010年首次公開[16]。也在同一年,其編譯器原始碼開始由原本的OCaml語言轉移到用Rust語言,進行bootstrapping工作,稱做「rustc」[17],並於2011年實際完成[18]。這個可自我編譯的編譯器在架構上採用了LLVM做為它的後端。
第一個有版本號的Rust編譯器於2012年1月釋出。[19]Rust 1.0是第一個穩定版本,於2015年5月15日釋出。[20]
Rust是在完全開放的情況下進行開發,並且相當歡迎社區的回饋。在1.0穩定版之前,語言設計也因為透過撰寫Servo網頁瀏覽器排版引擎和rustc編譯器本身,而有進一步的改善。雖然它由Mozilla資助,但它其實是一個共有專案,有很大部分的代碼是來自於社區的貢獻者。[21]
設計
Rust的設計目標之一,是要使設計大型的網際網路客户端和伺服器的任務變得更容易[22]。因此更加強調安全性、記憶體配置、以及並行處理等方面的特性。
Rust的性能
在效能上,具有額外安全保證的代碼會比C++慢一些,例如对Rust的数组进行操作时默认会检查索引是否越界,尽管可以通过一些方式[23]绕过[24],而C++则不会,但是如果以C++也手工提供保證的情況下,則兩者效能上是相似的[25]。
语法
Rust的語法設計,與C語言和C++相當相似,區塊(block)使用大括號隔開,流程控制的關鍵字如if
、else
、while
等等。在保持相似性的同時,Rust也加進了新的關鍵字,如用於模式匹配(pattern matching)的match
(與switch
相似)則是使用C/C++系統程式語言的人會相對陌生的概念。儘管在語法上相似,Rust的語義(semantic)和(C/C++)非常不同。
内存安全
為了提供記憶體安全,它的設計不允許空指標和懸空指標[26] [27]。 指針只能透過固定的初始化形態來建構,而所有這些形態都要求它們的輸入已經分析過了[28]。Rust有一個檢查指標生命期間和指標凍結的系統,可以用來預防在C++中許多的型別錯誤,甚至是用了智慧指標功能之後會發生的型別錯誤。
内存管理
早期的Rust雖然有垃圾回收系統,但非如Java或.NET平台的全自動垃圾回收。Rust 1.0已不再使用垃圾回收器,而是全面改用基于引用计数的智能指针来管理内存。
类型与多态
它的型別系統直接地模仿了Haskell語言的类型类概念,並把它稱作「traits」,可以把它看成是一種特设多态。Rust的作法是透過在宣告型別變數(type variable)的時候,在上面加上限制條件。至於Haskell的高階型別變數(Higher-kinded polymorphism)則還未支援。
型別推導也是Rust提供的特性之一,使用let
語法宣告的變數可以不用宣告型別,亦不需要初始值來推斷型別。但如果在稍後的程式中從未指派任何值到該變數,編譯器會發出編譯時(compile time)錯誤[29]。
函數可以使用泛型化參數(generics),但是必須綁定Trait。沒有任何方法可以使用方法或運算子,又不宣告它們的型別,每一項都必確明確定義。
Rust的物件系統是基於三樣東西之上的,即實作(implementation)、Trait以及結構化資料(如struct)。實作的角色類似提供Class關鍵字的程式語言所代表的意義,並使用impl
關鍵字。繼承和多型則透過Trait實現,它們使得方法(method)可以在實作中被定義。結構化資料用來定義欄位。實作和(trait)都無法定義欄位,並且只有(trait)可以提供繼承,藉以躲避C++的「鑽石繼承問題」(菱型缺陷)。
历史
2006年,Rust作为Graydon Hoare的个人项目首次出现。
2009年,Graydon Hoare成为Mozilla雇员[15]。
2010年,Rust首次作为Mozilla官方项目出现[16]。同年,Rust开始从初始编译(由OCaml写成)转变为自编译[17]。
2011年,Rust成功的完成了移植[18]。Rust的自编译器采用LLVM作为其编译后端。
2012年1月20日,第一个有版本号的预览版Rust编译器发布[19]。
2013年4月4日,Mozilla基金會宣布將與三星集團合作開發瀏覽器排版引擎Servo,此引擎将由Rust來實作[30]。
2015年5月16日,Rust 1.0.0发布[31]。
代码示例
下面的代码在Rust 1.3中测试通过。
Hello World
fn main() {
println!("Hello, World!");
}
階乘
下面是三個不同版本的階乘函數,分別以遞迴、迴圈和反覆運算器的方法寫成:
// 這個函數的if-else語句中展示了Rust中可選的隱式返回值,可用於寫出更像函數式程式設計風格的代碼
// 與C++和其他類似的語言不同,Rust中的if-else結構不是語句而是運算式,有返回值
fn recursive_factorial(n: u32) -> u32 {
if n <= 1 {
1
} else {
n * recursive_factorial(n - 1)
}
}
fn iterative_factorial(n: u32) -> u32 {
// 變數用`let`定義,`mut`關鍵字使得變數可以變化
let mut i = 1u32;
let mut result = 1u32;
while i <= n {
result *= i;
i += 1;
}
result // 顯式返回值,與上一個函數不同
}
fn iterator_factorial(n: u32) -> u32 {
// 反覆運算器有多種用於變換的函數
// |accum, x| 定義了一個匿名函數
// 內聯展開等優化方法會消去區間和fold,使本函數的運行效率和上一個函數相近
(1..n + 1).fold(1, |accum, x| accum * x)
}
fn main() {
println!("Recursive result: {}", recursive_factorial(10));
println!("Iterative result: {}", iterative_factorial(10));
println!("Iterator result: {}", iterator_factorial(10));
}
併發
一個簡單的Rust併發示例:
use std::thread;
// 這個函數將創建十個同時併發運行的執行緒
// 若要驗證這一點,可多次運行這個程式,觀察各執行緒輸出順序的隨機性
fn main() {
// 這個字串是不可變的,因此可以安全地同時被多個執行緒訪問
let greeting = "Hello";
let mut threads = Vec::new();
// `for`迴圈可用於任何實現了`iterator`特性的類型
for num in 0..10 {
threads.push(thread::spawn(move || {
// `println!`是一個可以靜態檢查格式字串類型的巨集
// Rust的巨集是基於結構的(如同Scheme)而不是基於文本的(如同C)
println!("{} from thread number {}", greeting, num);
}));
}
// 收集所有執行緒,保證它們在程式退出前全部結束
for thread in threads {
thread.join().unwrap();
}
}
參考資料
- . 2021年2月11日.
- . 2021年2月11日.
- . [2017-03-17]. (原始内容存档于2018-02-13).
- . Rust compiler source repository. [2012-12-17].
- . [2015-03-25]. (原始内容存档于2015-03-26).
Rust is not a particularly original language, with design elements coming from a wide range of sources. Some of these are listed below (including elements that have since been removed): SML, OCaml [...] C++ [...] ML Kit, Cyclone [...] Haskell [...] Newsqueak, Alef, Limbo [...] Erlang [...] Swift [...] Scheme [...] C# [...] Ruby [...] NIL, Hermes
- . 2015-02-01 [2015-03-25]. (原始内容存档于2019-02-17).
Papers that have had more or less influence on Rust, or which one might want to consult for inspiration or to understand Rust's background. [...] Region based memory management in Cyclone [...] Safe memory management in Cyclone
- . [2014-12-04]. (原始内容存档于2016-03-04).
The `if let` construct is based on the precedent set by Swift, which introduced its own `if let` statement.
- . 2015-03-25 [2015-03-25]. (原始内容存档于2015-08-19).
Sources of Inspiration: [...] Rust
- . 2014-06-26 [2014-12-10]. (原始内容存档于2019-07-08).
I just added the outline of a Result library that lets you use richer error messages. It's like Either except the names are more helpful. The names are inspired by Rust's Result library.
- . 2014-08-22 [2014-10-27]. (原始内容存档于2014-12-25).
They are inspired by linear types, Uniqueness Types in the Clean programming language, and ownership types and borrowed pointers in the Rust programming language.
- Lattner, Chris. . Chris Lattner. 2014-06-03 [2014-06-03]. (原始内容存档于2018-12-25).
The Swift language is the product of tireless effort from a team of language experts, documentation gurus, compiler optimization ninjas, and an incredibly important internal dogfooding group who provided feedback to help refine and battle-test ideas. Of course, it also greatly benefited from the experiences hard-won by many other languages in the field, drawing ideas from Objective-C, Rust, Haskell, Ruby, Python, C#, CLU, and far too many others to list.
- Noel. . Lambda the Ultimate. 2010-07-08 [2010-10-30]. (原始内容存档于2015-11-18).
- . [2012-10-21]. (原始内容存档于2016-06-18).
- . [2012-10-21]. (原始内容存档于2020-07-20).
- . 2010-09-14 [2012-01-11]. (原始内容存档于2020-07-20).
- . 2011-04-29 [2012-02-06]. (原始内容存档于2012-09-18).
At Mozilla Summit 2010, we launched Rust, a new programming language motivated by safety and concurrency for parallel hardware, the “manycore” future which is upon us.
- Hoare, Graydon. . 2010-10-02 [2010-10-30]. (原始内容存档于2014-08-15).
- Hoare, Graydon. . 2011-04-20 [2011-04-20]. (原始内容存档于2011-07-20).
After that last change fixing the logging scope context bug, looks like stage1/rustc builds. Just shy of midnight :)
- catamorphism. . 2012-01-20 [2012-02-06]. (原始内容存档于2012-01-24).
- . GitHub. [2015-07-26]. (原始内容存档于2015-05-15).
- . [2015-05-17]. (原始内容存档于2020-05-26).
- Avram, Abel. . InfoQ. 2012-08-03 [2013-08-17]. (原始内容存档于2013-07-24).
GH:在其他程式語言中有很多好的、討人喜愛的想法,沒有被廣泛採用的系統程式語言採納...在1970和80年代時,有些相當不錯的競爭者同時存在,我想要把它們所有的某些特性再拿出來,因為現況已經改變:網際網路是併發性非常強的系統,也更加重視安全性,所以以往獨鍾C以及C++的優勢不再成立。
- . The Rust Programming Language Forum. 2016-01-26 [2021-02-08] (英语).
- 范, 范长春. . 2018年8月第一版. 北京: 机械工业出版社. 2018: 72-73. ISBN 9787111606420. OCLC 1097888310.
- Walton, Patrick. . 2010-12-05 [2011-01-21]. (原始内容存档于2010-12-09).
...想要維持和C一樣快又同時保證安全是不可能的...C++在設計上允許各種低層操作,大部分與迴避型態系統有關,藉此C++有了幾乎無限制的最佳化能力。不過在實際上,C++工程師在自己的程式碼中只使用某些特定的工具或技巧,例如透過pass by alias傳遞stack變數、獨特擁有的物件(通常是
auto_ptr
或C++0x的unique_ptr
)、使用shared_ptr
來達成「引用計數」、COM等等。Rust的型態系統的設計目標之一,就是在語言中融入這些安全性設計,並且強迫實行這些原則。這樣的話,效能可以與C++比較,又能同時保持記憶體安全... - Rosenblatt, Seth. . 2013-04-03 [2013-04-05]. (原始内容存档于2013-04-04).
[Brendan Eich]提出,每一年,瀏覽器都會在Pwn2Own競賽上發現新的漏洞。他說,Rust「不允許自由讀取記憶體」,但C++則可以。這些便是「導致瀏覽器弱點」,也是能夠自編譯的Rust要解決的問題。
- Brown, Neil. . 2013-04-17 [2013-04-25]. (原始内容存档于2013-04-26).
...當然,為了更大程度的記憶體分享,使用者可以實作更複雜的資料結構,並同時保持介面只由被擁有和被管理的參照所組成。如此便解決了競爭存取和懸空指標的問題。
- . 2015-05-17 [2015-05-17]. (原始内容存档于2015-05-15).
- Walton, Patrick. . 2010-10-01 [2011-01-21]. (原始内容存档于2011-07-08).
- Peter Bright. . 2013-04-03 [2013-04-04]. (原始内容存档于2016-12-16).
- The Rust Core Team. . May 15, 2015 [2015-12-11]. (原始内容存档于2015-05-15).
- . foundation.rust-lang.org. 2021-02-08 [2021-02-09] (英语). 已忽略未知参数
|url-status=
(帮助) - . Mozilla Blog. 2021-02-09 [2021-02-09] (美国英语). 已忽略未知参数
|url-status=
(帮助)