型別推導

YouTube 上觀看本章內容

型別推導的意思是,如果你沒有告訴編譯器型別,但它可以自己判斷時它就會自己決定型別。編譯器總是必需知道變數的型別,但你不需要都告訴它。實際上,通常你不需要告訴它。例如,像 let my_number = 8my_number 將會是 i32。這是因為如果你不告訴它,編譯器會給整數選擇 i32。但是如果你說 let my_number: u8 = 8,它就會把 my_number 視為 u8,因為你明確告訴它是 u8

通常編譯器都能猜到。但有時你需要告訴它,原因有兩個:

  1. 你正在做一些非常複雜的事情,而編譯器不知道你想要的型別。
  2. 你想要一個不同的型別 (例如,你想要一個 i128,而不是 i32)。

這時可以指定一個型別,只要在變數名後新增一個冒號和型別。

fn main() {
    let small_number: u8 = 10;
}

對數字來說,你可以在數字後面加上型別。你不需要空格──只需要在數字後面直接輸入。

fn main() {
    let small_number = 10u8; // 10u8 = 型別為 u8 的 10
}

如果你想讓數字容易閱讀,也可以加上 _

fn main() {
    let small_number = 10_u8; // 好讀
    let big_number = 100_000_000_i32; // 用 _ 時更容易讀出是 100 百萬
}

_不會改變數字。它只是為了讓你方便閱讀。而且你用多少個_都沒有關係。

fn main() {
    let number = 0________u8;
    let number2 = 1___6______2____4______i32;
    println!("{}, {}", number, number2);
}

這個程式會印出 0, 1624.

浮點數

浮點數是帶有小數點的數字。5.5 是一個浮點數,6 是一個整數。5.0 也是一個浮點數,甚至 5. 也是一個浮點數。

fn main() {
    let my_float = 5.; // Rust 看到 . 時,知道它是 float
}

但寫出型別時不叫 float,叫 f32f64。這點和整數一樣:f 後面的數字顯示的是位元數。如果你不寫型別,Rust 會選擇 f64

當然,只有同樣型別的浮點數可以一起使用。所以你不能把 f32f64 加起來。

fn main() {
    let my_float: f64 = 5.0; // 這是 f64
    let my_other_float: f32 = 8.5; // 這是 f32

    let third_float = my_float + my_other_float; // ⚠️
}

當你嘗試執行這個程式時,Rust 會說:

error[E0308]: mismatched types
 --> src\main.rs:5:34
  |
5 |     let third_float = my_float + my_other_float;
  |                                  ^^^^^^^^^^^^^^ expected `f64`, found `f32`

當你用錯型別時,編譯器會寫 "expected (type), found (type)"。它是像這樣讀你的程式碼:

fn main() {
    let my_float: f64 = 5.0; // 編譯器見到 f64
    let my_other_float: f32 = 8.5; // 編譯器見到 f32 是個不同型別
    let third_float = my_float + // 你想把 my_float 加上什麼,所以它一定要是 f64 加上另一個 f64。現在它預期有另一個 f64…
    let third_float = my_float + my_other_float;  // ⚠️ 不過它發現是個 f32。它沒辨法把它們加起來。
}

所以當你看到 "expected(type), found(type)" 時,你必須找到為什麼編譯器預期的是不同的型別。

當然,單純的數字很容易修正。你可以用 asf32 轉型成 f64

fn main() {
    let my_float: f64 = 5.0;
    let my_other_float: f32 = 8.5;

    let third_float = my_float + my_other_float as f64; // my_other_float as f64 = 把 my_other_float 當 f64 來用
}

或者更簡單,去掉型別宣告。("宣告一個型別" = "告訴Rust使用該型別") Rust會選擇可以加在一起的型別。

fn main() {
    let my_float = 5.0; // Rust 會選 f64
    let my_other_float = 8.5; // 這裡還是會選 f64

    let third_float = my_float + my_other_float;
}

Rust 編譯器很聰明,如果你需要 f32,就不會選擇 f64:

fn main() {
    let my_float: f32 = 5.0;
    let my_other_float = 8.5; // 通常 Rust 是選 f64,

    let third_float = my_float + my_other_float; // 但現在它知道你需要把它加上 f32。所以它也選了 f32 給 my_other_float
}