Rust (程式語言)

出自Local Chinese Wikipedia
(重新導向自Rust語言
跳至導覽 跳至搜尋
Rust
File:Rust programming language black logo.svg
編程範型編譯語言並行計算
函數式指令式
物件導向結構化
設計者Graydon Hoare
實作者Mozilla
面市時間2010年
型態系統靜態類型強型別
類型推論結構類型英語Structural type system
作業系統LinuxmacOSWindows
FreeBSDAndroidiOS[1]
授權條款Apache授權條款2.0及MIT授權條款[2]
副檔名.rs、.rlib
網站rust-lang.org
受影響於
Alef英語Alef (programming language)[3]C#[3]C++[3]Cyclone英語Cyclone (programming language)[3][4]
Erlang[3]Haskell[3]Hermes英語Hermes (programming language)[3]Limbo[3]
Newsqueak[3]NIL英語NIL (programming language)[3]OCaml[3]Ruby[3]
Scheme[3]Standard ML[3]Swift[3][5]
影響語言
C# 7[6]Elm[7]Idris[8]Swift[9]Carbon

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

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

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

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

設計[編輯]

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

效能[編輯]

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

編譯報錯[編輯]

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

編譯速度[編輯]

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

語法[編輯]

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

主記憶體安全[編輯]

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

所有權[編輯]

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

主記憶體管理[編輯]

早期的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雇員[13]

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

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

2012年1月20日,第一個有版本號的預覽版Rust編譯器釋出[17]

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

2015年5月16日,Rust 1.0.0釋出[31]

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

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

2022年9月19日,Linux初始開發者 Linus Torvalds 表示在Linux核心6.1版中會有對Rust的初步支援[36]

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

生態系統[編輯]

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

Cargo[編輯]

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

Cargo.toml檔案指定了專案所需的依賴和版本要求,告訴Cargo哪些版本的依賴關係與該包相容。Cargo預設從crates.io中取得依賴,但Git倉庫和本地檔案系統中的包也可以作為依賴。[39]

整合式開發環境支援[編輯]

rust-analyzer 是一系列工具,可以通過語言伺服器協定整合式開發環境(IDE)和文字編輯器提供有關某一Rust專案的資訊。利用它,開發者可以在編輯Rust程式碼時使用自動完成和編譯錯誤顯示等功能。[40]

程式碼範例[編輯]

下面的程式碼在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. Rust Platform Support. [2017-03-17]. (原始內容存檔於2018-02-13). 
  2. COPYRIGHT. Rust compiler source repository. [2012-12-17]. 
  3. 3.00 3.01 3.02 3.03 3.04 3.05 3.06 3.07 3.08 3.09 3.10 3.11 3.12 3.13 3.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 
  4. 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 
  5. 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. 
  6. Discussion - Patterns and Records. 2015-03-25 [2015-03-25]. (原始內容存檔於2015-08-19). Sources of Inspiration: [...] Rust 
  7. 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. 
  8. 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. 
  9. 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. 
  10. Noel. The Rust Language. Lambda the Ultimate. 2010-07-08 [2010-10-30]. (原始內容存檔於2015-11-18). 
  11. The Rust Programming Language. [2012-10-21]. (原始內容存檔於2016-06-18). 
  12. Doc language FAQ. [2012-10-21]. (原始內容存檔於2020-07-20). 
  13. 13.0 13.1 Project FAQ. 2010-09-14 [2012-01-11]. (原始內容存檔於2020-07-20). 
  14. 14.0 14.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. 
  15. 15.0 15.1 Hoare, Graydon. Rust Progress. 2010-10-02 [2010-10-30]. (原始內容存檔於2014-08-15). 
  16. 16.0 16.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 :) 
  17. 17.0 17.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). 
  18. rust/RELEASES.md at master · rust-lang/rust · GitHub. GitHub. [2015-07-26]. (原始內容存檔於2015-05-15). 
  19. Rust Contributors. [2015-05-17]. (原始內容存檔於2020-05-26). 
  20. 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++的優勢不再成立。 
  21. How to avoid bounds checking?. The Rust Programming Language Forum. 2016-01-26 [2021-02-08]. (原始內容存檔於2021-02-08) (English). 
  22. 范, 范長春. 数组和字符串. 深入浅出Rust 2018年8月第一版. 北京: 機械工業出版社. 2018: 72-73. ISBN 9787111606420. OCLC 1097888310. 
  23. 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++比較,又能同時保持記憶體安全... 
  24. Rosenblatt, Seth. Samsung joins Mozilla's quest for Rust. 2013-04-03 [2013-04-05]. (原始內容存檔於2013-04-04). [Brendan Eich]提出,每一年,瀏覽器都會在Pwn2Own競賽上發現新的漏洞。他說,Rust「不允許自由讀取記憶體」,但C++則可以。這些便是「導致瀏覽器弱點」,也是能夠自編譯的Rust要解決的問題。 
  25. Brown, Neil. A taste of Rust. 2013-04-17 [2013-04-25]. (原始內容存檔於2013-04-26). ...當然,為了更大程度的記憶體分享,使用者可以實作更複雜的資料結構,並同時保持介面只由被擁有和被管理的參照所組成。如此便解決了競爭存取和懸空指標的問題。 
  26. Language FAQ. 2015-05-17 [2015-05-17]. (原始內容存檔於2015-05-15). 
  27. 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) (English). 
  28. The Rust Programming Language: What is Ownership. Rust-lang.org. [2019-05-14]. (原始內容存檔於2019-05-19) (English). 
  29. Walton, Patrick. Rust Features I: Type Inference. 2010-10-01 [2011-01-21]. (原始內容存檔於2011-07-08). 
  30. Peter Bright. Samsung teams up with Mozilla to build browser engine for multicore machines. 2013-04-03 [2013-04-04]. (原始內容存檔於2016-12-16). 
  31. The Rust Core Team. Announcing Rust 1.0. May 15, 2015 [2015-12-11]. (原始內容存檔於2015-05-15). 
  32. Goodbye, docs team. [2022-10-10]. (原始內容存檔於2022-12-01) (English). 
  33. Rust Foundation. foundation.rust-lang.org. 2021-02-08 [2021-02-09]. (原始內容存檔於2021-02-09) (English). 
  34. Mozilla Welcomes the Rust Foundation. Mozilla Blog. 2021-02-09 [2021-02-09]. (原始內容存檔於2021-02-08) (en-US). 
  35. 抛弃 C / C++!微软官宣:请用 Rust 编写 Windows 驱动!. CSDNnews. 2023-10-08 [2023-10-09]. (原始內容存檔於2023-10-09) (中文(中國大陸)). 
  36. Linus Torvalds: Rust will go into Linux 6.1. ZDNET. [2022-10-06]. (原始內容存檔於2023-01-19) (English). 
  37. Claburn, Thomas. Rust Foundation apologizes for trademark policy confusion. The Register. 2023-04-17 [2023-05-07]. (原始內容存檔於2023-05-07) (English). 
  38. Why Cargo Exists - The Cargo Book. doc.rust-lang.org. [2022-02-01]. (原始內容存檔於2022-04-07). 
  39. Specifying Dependencies - The Cargo Book. doc.rust-lang.org. [2022-02-01]. (原始內容存檔於2022-04-07). 
  40. Klabnik, Steve; Nichols, Carol. The Rust programming language. San Francisco: No Starch Press. San Francisco: 623. ISBN 978-1-7185-0310-6. 

參閱[編輯]

外部連結[編輯]