Rust

重視記憶體安全性與並行處理的程式語言

Rust是由Mozilla[11]主導開發的通用編譯型編程語言。設計準則為「安全、並發、實用」[12][13],支持函數式並行式過程式以及面向對象的程式設計風格。

Rust
編程範型編譯語言並行計算
函數式指令式
物件導向結構化
設計者Graydon Hoare
實作者Mozilla
面市時間2010年
當前版本
  • 1.83.0(2024年11月28日;穩定版本)[1]
編輯維基數據鏈接
型態系統靜態類型強型別
類型推論結構類型英語Structural type system
操作系統LinuxmacOSWindows
FreeBSDAndroidiOS[2]
許可證Apache許可證2.0及MIT許可證[3]
文件擴展名.rs、.rlib
網站rust-lang.org
啟發語言
Alef英語Alef (programming language)[4]C#[4]C++[4]Cyclone英語Cyclone (programming language)[4][5]
Erlang[4]Haskell[4]Hermes英語Hermes (programming language)[4]Limbo[4]
Newsqueak[4]NIL英語NIL (programming language)[4]OCaml[4]Ruby[4]
Scheme[4]Standard ML[4]Swift[4][6]
影響語言
C# 7[7]Elm[8]Idris[9]Swift[10]Carbon

Rust語言原本是Mozilla員工Graydon Hoare的個人專案,而Mozilla於2009年開始贊助這個專案 [14],並且在2010年首次公開[15]。也在同一年,其編譯器原始碼開始由原本的OCaml語言轉移到用Rust語言,進行自我編譯工作,稱做「rustc」[16],並於2011年實際完成[17]。這個可自我編譯的編譯器在架構上採用了LLVM做為它的後端。

第一個有版本號的Rust編譯器於2012年1月釋出[18]。Rust 1.0是第一個穩定版本,於2015年5月15日釋出[19]

Rust在完全公開的情況下開發,並且相當歡迎社群的回饋。在1.0穩定版之前,語言設計也因為透過撰寫Servo網頁瀏覽器排版引擎和rustc編譯器本身,而有進一步的改善。它雖然由Mozilla資助,但其實是一個共有專案,有很大部分的程式碼是來自於社群的貢獻者[20]

設計

編輯

Rust的設計目標之一,是要使設計大型的網際網路客戶端伺服器的任務變得更容易[21]。因此更加強調安全性、記憶體配置、以及並行處理等方面的特性。

性能

編輯

在效能上,具有額外安全保證的代碼會比C++慢一些,例如Rust對數組進行操作時會進行邊界檢查(儘管可以通過一些方式[22]繞過[23]),而C++則不會,但是如果等價的C++代碼作手工檢查,則兩者效能上是相似的[24]

編譯報錯

編輯

比起C/C++,Rust編譯器的對於代碼中錯誤的提示更清晰明瞭,開發者可根據提示輕鬆地修復代碼中的錯誤。

編譯速度

編輯

由於其編譯器會做出額外的安全檢查,Rust的編譯速度有時低於C/C++。

語法

編輯

Rust的語法設計,與C語言C++相當相似,區塊(block)使用大括號隔開,控制流程的關鍵字如ifelsewhile等等。在保持相似性的同時,Rust也加進了新的關鍵字,如用於模式匹配match(與switch相似)則是使用C/C++系統程式語言的人會相對陌生的概念。儘管在語法上相似,Rust的語義(semantic)和C/C++非常不同。

內存安全

編輯

為了提供內存安全,它的設計不允許空指標懸空指標[25][26]。指針只能透過固定的初始化形態來建構,而所有這些形態都要求它們的輸入已經分析過了[27]。Rust有一個檢查指標生命期間和指標凍結的系統,可以用來預防在C++中許多的型別錯誤,甚至是用了智能指針功能之後會發生的型別錯誤。

所有權

編輯

Rust設計了一個所有權系統,其中所有值都有一個唯一的所有者,並且值的作用域與所有者的作用域相同。值可以通過不可變引用(&T)、可變引用(&mut T)或者通過值本身(T)傳遞。任何時候,一個變量都可以有多個不可變引用或一個可變引用,這實際上是一個顯式的讀寫鎖。Rust編譯器在編譯時強制執行這些規則,並檢查所有引用是否有效。[28][29]

內存管理

編輯

早期的Rust雖然有垃圾回收系統,但非如Java.NET平台的全自動垃圾回收。Rust 1.0已不再使用垃圾回收器,而是全面改用基於引用計數的智能指針來管理內存。

類型與多態

編輯

它的型別系統直接地模仿了Haskell語言的類型類概念,並把它稱作「traits」,可以把它看成是一種特設多態。Rust的作法是透過在宣告型別變數(type variable)的時候,在上面加上限制條件。至於Haskell的高階型別變數(Higher-kinded polymorphism)則還未支援。

型別推導也是Rust提供的特性之一,使用let語法宣告的變數可以不用宣告型別,亦不需要初始值來推斷型別。但如果在稍後的程式中從未指派任何值到該變數,編譯器會發出編譯時(compile time)錯誤[30]。函數可以使用泛型化參數(generics),但是必須綁定Trait。不能使用方法或運算子而不宣告它們的型別,每一項都必確明確定義。

Rust的物件系統是基於三樣東西之上的,即實作(implementation)、Trait以及結構化資料(如struct)。實作的角色類似提供Class關鍵字的程式語言所代表的意義,並使用impl關鍵字。繼承和多型則透過Trait實現,它們使得方法(method)可以在實作中被定義。結構化資料用來定義欄位。實作和(trait)都無法定義欄位,並且只有(trait)可以提供繼承,藉以躲避C++的「鑽石繼承問題」(菱型缺陷)。

歷史

編輯

2006年,Rust作為Graydon Hoare的個人項目首次出現。

2009年,Graydon Hoare成為Mozilla雇員[14]

2010年,Rust首次作為Mozilla官方項目出現[15]。同年,Rust開始從初始編譯(由OCaml寫成)轉變為自編譯[16]

2011年,Rust成功的完成了移植[17]。Rust的自編譯器採用LLVM作為其編譯後端。

2012年1月20日,第一個有版本號的預覽版Rust編譯器發布[18]

2013年4月4日,Mozilla基金會宣布將與三星集團合作開發瀏覽器排版引擎Servo,此引擎將由Rust來實作[31]

2015年5月16日,Rust 1.0.0發布[32]

2020年3月27日,Rust核心團隊成員Steve Klabnik在官方博客發表了一篇名為《Goodbye, docs team》的文章,敘述了Rust文檔的現狀[33]

2021年2月8日,AWS華為Google微軟以及Mozilla宣布成立Rust基金會[34][35],並承諾在兩年時間裡每年投入不少於 100 萬美元的預算,以用於 Rust 項目的開發、維護和推廣[36]

2022年9月19日,Linux初始開發者林納斯·托瓦茲表示在Linux核心6.1版中會有對Rust的初步支援[37]

2023年4月6日,Rust基金會發布了新商標政策草案,修訂了關於如何使用Rust標誌和名稱的規則,導致了Rust用戶社區的負面反應和抗議。[38]

生態系統

編輯

除了編譯器和標準庫,Rust生態系統還包括用於軟件開發的額外組件。官方推薦使用Rustup,一個Rust工具鏈安裝程序來管理這些組件。

Cargo是Rust的軟件包管理器,用來下載和構建依賴關係。Cargo還充當了Clippy和其他Rust組件的封裝器。它要求項目遵循一定的目錄結構。[39]

Cargo.toml文件指定了項目所需的依賴和版本要求,告訴Cargo哪些版本的依賴關係與該包兼容。Cargo默認從crates.io中獲取依賴,但Git倉庫和本地文件系統中的包也可以作為依賴。[40]

集成開發環境支持

編輯

rust-analyzer 是一系列工具,可以通過語言服務器協議集成開發環境(IDE)和文本編輯器提供有關某一Rust項目的信息。利用它,開發者可以在編輯Rust代碼時使用自動完成和編譯錯誤顯示等功能。[41]

代碼示例

編輯

下面的代碼在Rust 1.3中測試通過。

Hello World

編輯
fn main() {
    println!("Hello, World!");
}

如果不想使輸出包含換行符(\n),可以使用print!巨集代替println!巨集。

階乘

編輯

下面是三個不同版本的階乘函數,分別以遞迴迴圈迭代器的方法寫成:

// 這個函數的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();
    }
}

參考資料

編輯
  1. ^ Announcing Rust 1.83.0. 2024年11月28日 [2024年11月28日] (英語). 
  2. ^ Rust Platform Support. [2017-03-17]. (原始內容存檔於2018-02-13). 
  3. ^ COPYRIGHT. Rust compiler source repository. [2012-12-17]. 
  4. ^ 4.00 4.01 4.02 4.03 4.04 4.05 4.06 4.07 4.08 4.09 4.10 4.11 4.12 4.13 4.14 The Rust Reference: Appendix: Influences. [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 
  5. ^ Note Research: Type System. 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 
  6. ^ RFC for `if let` expression. [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. 
  7. ^ Discussion - Patterns and Records. 2015-03-25 [2015-03-25]. (原始內容存檔於2015-08-19). Sources of Inspiration: [...] Rust 
  8. ^ Command Optimizations?. 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. 
  9. ^ Uniqueness Types. 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. 
  10. ^ Lattner, Chris. Chris Lattner's Homepage. 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. 
  11. ^ Noel. The Rust Language. Lambda the Ultimate. 2010-07-08 [2010-10-30]. (原始內容存檔於2015-11-18). 
  12. ^ The Rust Programming Language. [2012-10-21]. (原始內容存檔於2016-06-18). 
  13. ^ Doc language FAQ. [2012-10-21]. (原始內容存檔於2020-07-20). 
  14. ^ 14.0 14.1 Project FAQ. 2010-09-14 [2012-01-11]. (原始內容存檔於2020-07-20). 
  15. ^ 15.0 15.1 Future Tense. 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. 
  16. ^ 16.0 16.1 Hoare, Graydon. Rust Progress. 2010-10-02 [2010-10-30]. (原始內容存檔於2014-08-15). 
  17. ^ 17.0 17.1 Hoare, Graydon. [rust-dev] stage1/rustc builds. 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 :) 
  18. ^ 18.0 18.1 catamorphism. Mozilla and the Rust community release Rust 0.1 (a strongly-typed systems programming language with a focus on memory safety and concurrency). 2012-01-20 [2012-02-06]. (原始內容存檔於2012-01-24). 
  19. ^ rust/RELEASES.md at master · rust-lang/rust · GitHub. GitHub. [2015-07-26]. (原始內容存檔於2015-05-15). 
  20. ^ Rust Contributors. [2015-05-17]. (原始內容存檔於2020-05-26). 
  21. ^ Avram, Abel. Interview on Rust, a Systems Programming Language Developed by Mozilla. InfoQ. 2012-08-03 [2013-08-17]. (原始內容存檔於2013-07-24). GH:在其他程式語言中有很多好的、討人喜愛的想法,沒有被廣泛採用的系統程式語言採納...在1970和80年代時,有些相當不錯的競爭者同時存在,我想要把它們所有的某些特性再拿出來,因為現況已經改變:網際網路是併發性非常強的系統,也更加重視安全性,所以以往獨鍾C以及C++的優勢不再成立。 
  22. ^ How to avoid bounds checking?. The Rust Programming Language Forum. 2016-01-26 [2021-02-08]. (原始內容存檔於2021-02-08) (英語). 
  23. ^ 范, 范長春. 数组和字符串. 深入浅出Rust 2018年8月第一版. 北京: 機械工業出版社. 2018: 72-73. ISBN 9787111606420. OCLC 1097888310. 
  24. ^ Walton, Patrick. C++ Design Goals in the Context of Rust. 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++比較,又能同時保持記憶體安全... 
  25. ^ Rosenblatt, Seth. Samsung joins Mozilla's quest for Rust. 2013-04-03 [2013-04-05]. (原始內容存檔於2013-04-04). [Brendan Eich]提出,每一年,瀏覽器都會在Pwn2Own競賽上發現新的漏洞。他說,Rust「不允許自由讀取記憶體」,但C++則可以。這些便是「導致瀏覽器弱點」,也是能夠自編譯的Rust要解決的問題。 
  26. ^ Brown, Neil. A taste of Rust. 2013-04-17 [2013-04-25]. (原始內容存檔於2013-04-26). ...當然,為了更大程度的記憶體分享,使用者可以實作更複雜的資料結構,並同時保持介面只由被擁有和被管理的參照所組成。如此便解決了競爭存取和懸空指標的問題。 
  27. ^ Language FAQ. 2015-05-17 [2015-05-17]. (原始內容存檔於2015-05-15). 
  28. ^ Klabnik, Steve; Nichols, Carol. Chapter 4: Understanding Ownership. The Rust Programming Language. San Francisco, California: No Starch Press. June 2018: 44 [2019-05-14]. ISBN 978-1-593-27828-1. (原始內容存檔於2019-05-03) (英語). 
  29. ^ The Rust Programming Language: What is Ownership. Rust-lang.org. [2019-05-14]. (原始內容存檔於2019-05-19) (英語). 
  30. ^ Walton, Patrick. Rust Features I: Type Inference. 2010-10-01 [2011-01-21]. (原始內容存檔於2011-07-08). 
  31. ^ Peter Bright. Samsung teams up with Mozilla to build browser engine for multicore machines. 2013-04-03 [2013-04-04]. (原始內容存檔於2016-12-16). 
  32. ^ The Rust Core Team. Announcing Rust 1.0. May 15, 2015 [2015-12-11]. (原始內容存檔於2015-05-15). 
  33. ^ Goodbye, docs team. [2022-10-10]. (原始內容存檔於2022-12-01) (英語). 
  34. ^ Rust Foundation. foundation.rust-lang.org. 2021-02-08 [2021-02-09]. (原始內容存檔於2021-02-09) (英語). 
  35. ^ Mozilla Welcomes the Rust Foundation. Mozilla Blog. 2021-02-09 [2021-02-09]. (原始內容存檔於2021-02-08) (美國英語). 
  36. ^ 抛弃 C / C++!微软官宣:请用 Rust 编写 Windows 驱动!. CSDNnews. 2023-10-08 [2023-10-09]. (原始內容存檔於2023-10-09) (中文(中國大陸)). 
  37. ^ Linus Torvalds: Rust will go into Linux 6.1. ZDNET. [2022-10-06]. (原始內容存檔於2023-01-19) (英語). 
  38. ^ Claburn, Thomas. Rust Foundation apologizes for trademark policy confusion. The Register. 2023-04-17 [2023-05-07]. (原始內容存檔於2023-05-07) (英語). 
  39. ^ Why Cargo Exists - The Cargo Book. doc.rust-lang.org. [2022-02-01]. (原始內容存檔於2022-04-07). 
  40. ^ Specifying Dependencies - The Cargo Book. doc.rust-lang.org. [2022-02-01]. (原始內容存檔於2022-04-07). 
  41. ^ Klabnik, Steve; Nichols, Carol. The Rust programming language. San Francisco: No Starch Press. San Francisco: 623. ISBN 978-1-7185-0310-6. 

參閱

編輯

外部連結

編輯