---
# System prepended metadata

title: Rust

---

# Rust
## Rust tooling and ecosystem
- [Rust in the Linux kernel - Google Security Blog](https://security.googleblog.com/2021/04/rust-in-linux-kernel.html)
    - 不是全部用Rust改寫Linux kernel，目標是能夠用Rust能夠zero-cost使用Kernel的C API、原有C撰寫的Kernel能使用以Rust寫的新功能
    - 有semaphore使用C和Rust的比較範例 (還沒看)
    - Android已支援Rust開發OS本身
- [Rust for Linux - Github](https://github.com/Rust-for-Linux/linux)
- [Linux kernel modules in safe Rust - Github](https://github.com/fishinabarrel/linux-kernel-module-rust)
- [我眼中的 Rust 2020：生態工具發展](https://weihanglo.tw/posts/2020/rust-2020-tooling-ecosystem/)
    - 各種工具和專案
- [Rust for C++ programmers](https://github.com/nrc/r4cppp)
    - A Rust tutorial for experienced C and C++ programmers.
- [【譯】Rust vs. Go](https://weihanglo.tw/posts/2018/rust-vs-go/)
    - 強力推薦在座的各位學習 Rust，與 borrow checker 與 ownership 和平共處。即使最終你並沒有使用 Rust，過程中所學都會回饋到其他語言上，連 Go 也不例外。
## Rust 語法簡介
- [給 C++ 使用者的 Rust 簡介 - electronic.blue](https://electronic.blue/blog/2016/10/10-rust-an-introduction/) (有一系列簡要的文章)
    - Rust 的目標是成為高效率、易於平行運算的系統程式語言，因此它選擇了以下的特性：
        - 靜態型別 (static-typed)
        - 區分 mutable 與 immutable，所有變數預設為 immutable，盡可能減少 mutable state
        - 使用 tagged union 與 pattern matching
        - 不使用動態垃圾回收 (garbage collection)，而使用靜態的 RAII
        - 使用 Move semantics 避免複製物件
        - 使用 borrow checker 確保 memory safety 與 thread safety
    - Move Semantics
        - Rust 並沒有 class，那麼 rust 的 struct 是 value-type 還是 reference-type 呢？我們試著用最簡單的做法來判定 value-type 與 reference-type：宣告一個物件，用等號賦值給另一個物件並修改其內容，然後檢查原物件的值是否變動。對 value-type 來說是不變動的，而對 reference-type 來說，因為兩個變數實際指向同一塊記憶體，因此內容會變動。然而，這兩種狀況都不會發生在 Rust 上面，因為 compiler 把它擋下來了。
        ```Rust=
        struct Point {
            x: i32,
            y: i32,
        }
        fn main() {
            let mut foo = Point { x: 10, y: 20 };
            let mut bar = foo;
            bar.x = 30;
            println!("foo.x = {}", foo.x); // error: use of moved value `foo.x`
        }
        ```
        - 為了使用上的方便，Rust 的基本型別，都具備可複製的特性。因此使用等號賦值時，進行的動作是「複製」，讓你可以繼續操作右值。
    - 表達式
        - Rust 是 expression-oriented language，大部份的流程控制結構，比如說 if，其實都是可以求值的表達式。
        - 分號可以用來分隔表達式，最後一個不帶分號的表達式會成為整個表達式的結果，因此 is_leap 會根據條件判斷，成為 "is" 或 "is not"。注意第七行與第九行都不能加分號，要是最後一個運算式也加上分號，那麼整個運算式的結果會變成 ()，也就是那個沒啥用的 0-tuple。而在第 11 行的分號則用來區隔 let 變數宣告與 println!，是一定要加上去的。
        > 為何表達式會變tuple? 
        ```Rust=
        let year = 2016;
        let is_leap = {
                          let div_4 = (year % 4 == 0);
                          let div_100 = (year % 100 == 0);
                          let div_400 = (year % 400 == 0);
                          if div_400 || (div_4 && !div_100) {
                              "is"
                          } else {
                              "is not"
                          }
                      };
        println!("Year {} {} a leap year.", year, is_leap);
        ```
    - 函式
        - 函式本體也是可以使用分號區隔的表達式，最後一個不帶分號的表達式會自動成為函式的回傳值，因此上一段檢查閏年的函式可以這樣寫：
        ```Rust=
        fn is_leap(year: i32) -> bool {
            let div_4 = (year % 4 == 0);
            let div_100 = (year % 100 == 0);
            let div_400 = (year % 400 == 0);
            div_400 || (div_4 && !div_100)
        }
        ```
        - 即使函式不回傳任何值，它還是有回傳型別，也就是上面提到那個好像沒啥用的 0-tuple。這看起來好像沒什麼用，畢竟 0-tuple 什麼事都做不了。然而，當你要寫泛型函式 (generic function) 時，你會跪在電腦前感謝這個設計。
        ```Rust=
        fn say_hello() -> () { // -> () 可省略
            println!("hello world");
        }
        fn main() { // 若無回傳型別，rust 會自動加上 -> ()
            let result = say_hello(); // 合法，result 的值為 ()
        }
        ```
    - 泛型
        - 如同 C++ 那般，Rust 也可以利用模版 (template) 來達成泛型程式設計，語法也非常接近 C++。與 C++ 不同的是，大部份情況下 Rust 都能藉由前後文來自動推導出正確的模版型別，因此上面的例子中並不需要特別加入 \<i32> 或是 \<f64>，直接用 Point 即可。
        ```Rust=
        struct Point<T> { // 相當於 template<typename T> struct Point
            x: T,
            y: T,
            z: T,
        }
        fn main() {
            let point_i32 = Point { x: 10, y: 20, z: 30 };
            let point_f64 = Point { x: 2.078, y: 0.454, z: 3.1415 };
        }
        ```
        - 泛型非常適合用來實作容器型別，比如 Rust 提供的 Vec 泛型容器，就相當於 C++ 的 std::vector。同樣地，因為 Rust 從第三行的 push(1) 判斷出 array 的元素型別為 i32，因此在第二行就不需要寫明 Vec\<i32>::new()，直接寫 Vec::new() 即可。
        ```Rust=
        fn main() {
            let mut array = Vec::new();
            array.push(1);
            array.push(2);
            println!("{}", array[0] + array[1]);
        }
        ```
        - 除了泛型類別，模版也可以用來定義泛型函式，然而與目前 C++ 不同的地方是，在 Rust 中，對泛型型別進行操作前，必需為它標上 constraint。這邊 Add 意指 T 必需是可以使用加號相加的型別，包括整數及浮點數都包括在內。由於相加後輸出型別不一定仍然為 T，因此這個函式的回傳型別是 T::Output。Rust 也支援運算子覆載 (operator overloading)，只要你的自訂型別定義了加號操作以及輸出型別，那麼這個自訂型別也可以直接傳入 sum 進行運算。
        > 很像C++ 20的concept
        ```Rust=
        fn sum<T: Add>(a: T, b: T) -> T::Output {
            a + b
        }
        ```
- [Rust基礎概念 - Michael Chen](https://michaelchen.tech/rust-programming/intro/)
    - Rust的安全性
        - 而 Rust 中，透過嚴格的編譯器，將許多 C 或 C++ 中相對危險的操作視為程式的錯誤，但仍保有一些操作指標的自由。嚴格的編譯器使得 Rust 較難上手，以前在程式執行時發生的錯誤，現在提早到編譯時就發現。往好處想，當程式能順利編譯時，該程式的錯誤也比較少。
    - Rust 的效能
        - 一些評效 (benchmark) 顯示，在相同演算法的前提下，Rust 程式已有接近等效 C++ 程式的執行速度。
        - 在實務中，已經有人用 Rust 撰寫遊戲引擎 (game engine) (如 Piston) 和作業系統 (operating system) (如 Redox)，而這些項目都對效能有較高需求，可以知道 Rust 已有足夠的效能和低階操作，應對不同層面的任務。
    - 在多核處理器中使用 Rust
        - Rust 同樣將安全的特性放入共時性程式中，讓程式設計者在安全的前提下，撰寫共時運算的程式。
    - Rust 的應用範圍
        - 使用 C 或 C++ 仍然要去面對平台間的差異，所以才需要撰寫條件式編譯相關程式碼。撰寫 Rust 程式碼時，不用再撰寫條件式編譯的程式碼，也就是說，Rust 程式碼是跨平台的。
        - 雖然 Rust 的角色類似 C 和 C++，但是，許許多多以 C 和 C++ 撰寫的函式庫，已經相當成熟穩健，重新以 Rust 實作這些函式庫不是明智的選擇，而 Rust 提供介面讓我們很容易地再利用這些函式庫，減少重造輪子所浪費的心力。
    - 使用 Rust 的注意事項
        - 因為剛發展的緣故，網路上一些關於 Rust 的文章變成錯誤的資訊，學習者透過網路學習 Rust 時，需多方嘗試。隨著 1.0 版發布，Rust 的核心特性大抵上穩定下來，這個問題逐漸減少。
        - 目前的函式庫 (library) 和框架 (framework) 沒有那麼豐富
    - Rust vs. C++
        - C++ 傾向於在語言層次提供各種豐富的機制，讓使用者從中自由組合出期待的效果，這也使得 C++ 成為一個複雜的語言；Rust 也有豐富的語法機制，不過，Rust 吸收了許多函數式語言的特色，寫起來和 C/C++ 風格的語言有所不同，需要一段時間來適應。
        - C++ 將記憶體管理的責任留給使用者，Rust 則自動處理大部份的記憶體操作。比起 C++，Rust 的編譯器較為嚴格，將許多常見的錯誤提前到編譯時期，使得程式更為安全。
    - Rust vs. Go
        - Go 使用一套簡單易學的語法機制，使用者可以很快熟悉大部分 Go 的特性，將其使用在自己的專案，但是，Go 缺乏部分重要的語法特性，為了向下相容，短期內這些問題不會改變；Rust 的語法機制則較完整，但語法不穩定的問題，使得 Rust 函式庫相對不穩定。
        - 另外，Go 依賴垃圾回收，使得 Go 較不適合即時運算 (real-time computing) 方面的應用，而 Rust 沒有這個問題。

- [Rust for C++ programmers](https://github.com/nrc/r4cppp)

## Rust 練習題
### Rust by Example
https://doc.rust-lang.org/rust-by-example/index.html
> Rust by Example (RBE) is a collection of runnable examples that illustrate various Rust concepts and standard libraries.
### rustlings
https://github.com/rust-lang/rustlings
> Small exercises to get you used to reading and writing Rust code! 
### The Algorithms - Rust
https://github.com/TheAlgorithms/Rust
> All algorithms implemented in Rust - for education

## Rust 效能
- [The Rust Performance Book](https://nnethercote.github.io/perf-book/title-page.html)