Rust語言介紹【維基百科】

維基百科鏈接點我

Rust是一個由Mozilla[11]主導開發的通用、編譯型編程語言。它的設計準則爲“安全,併發,實用”,[12][13]支持函數式併發式過程式以及面向對象的編程風格。

Rust 語言原本是 Mozilla 員工 Graydon Hoare 的私人項目,而 Mozilla 於 2009 年開始贊助這個項目[14],並且在 2010 年首次揭露了它的存在[15]。也在同一年,它的編譯器源代碼開始由原本的 OCaml 語言轉移到用 Rust 語言,進行 bootstrapping 工作,稱做 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++ 慢一些,但是如果以 C++ 也手工提供保證的情況下,則兩者性能上是相似的[22]

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

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

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

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

類型推導也是 Rust 提供的特性之一,使用 let 語法宣告的變量可以不用宣告類型,亦不需要初始值來推斷類型。但如果在稍後的程序中從未指派任何值到該變量,編譯器會發出編譯時 (compile time) 錯誤[26]。 函數可以使用泛型化參數 (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來實現[27]

2015年5月16日,Rust 1.0.0發佈[28]

代碼示例

下面的代碼在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();
    }
}
發佈了142 篇原創文章 · 獲贊 337 · 訪問量 224萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章